diff --git a/web/apps/photos/src/pages/cluster-debug.tsx b/web/apps/photos/src/pages/cluster-debug.tsx
index dcffaecfd2..23930f1f03 100644
--- a/web/apps/photos/src/pages/cluster-debug.tsx
+++ b/web/apps/photos/src/pages/cluster-debug.tsx
@@ -4,10 +4,9 @@ import {
faceCrop,
wipClusterDebugPageContents,
type ClusterDebugPageContents,
- type FaceFileNeighbour,
- type FaceFileNeighbours,
+ type ClusterPreviewFaceWF,
+ type ClusterPreviewWF,
} from "@/new/photos/services/ml";
-import type { Face } from "@/new/photos/services/ml/face";
import {
FlexWrapper,
FluidContainer,
@@ -15,7 +14,7 @@ import {
} from "@ente/shared/components/Container";
import EnteSpinner from "@ente/shared/components/EnteSpinner";
import BackButton from "@mui/icons-material/ArrowBackOutlined";
-import { Box, IconButton, styled, Typography } from "@mui/material";
+import { Box, IconButton, Stack, styled, Typography } from "@mui/material";
import { useRouter } from "next/router";
import { AppContext } from "pages/_app";
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
@@ -53,8 +52,9 @@ export default function ClusterDebug() {
{`${clusterRes.clusters.length} clusters`}
- Showing only top 20 and bottom 10 clusters (and only up to 50 faces in
- each, sorted by cosine distance to highest scoring face in the cluster).
+ Showing only top 20 and bottom 10 clusters (and only up to 50
+ faces in each, sorted by cosine distance to highest scoring face
+ in the cluster).
@@ -112,7 +112,7 @@ const ClusterPhotoList: React.FC = ({
width,
clusterRes,
}) => {
- const { faceFNs, clusterIDForFaceID } = clusterRes;
+ const { clusterPreviewWFs, clusterIDForFaceID } = clusterRes;
const [itemList, setItemList] = useState([]);
const listRef = useRef(null);
@@ -125,8 +125,8 @@ const ClusterPhotoList: React.FC = ({
const listItemHeight = 120 * shrinkRatio + 24 + 4;
useEffect(() => {
- setItemList(itemListFromFaceFNs(faceFNs, columns));
- }, [columns, faceFNs]);
+ setItemList(itemListFromClusterPreviewWFs(clusterPreviewWFs, columns));
+ }, [columns, clusterPreviewWFs]);
useEffect(() => {
listRef.current?.resetAfterIndex(0);
@@ -138,7 +138,7 @@ const ClusterPhotoList: React.FC = ({
const generateKey = (i: number) =>
Array.isArray(itemList[i])
? `${itemList[i][0].enteFile.id}/${itemList[i][0].face.faceID}-${itemList[i].slice(-1)[0].enteFile.id}/${itemList[i].slice(-1)[0].face.faceID}-${i}`
- : `${itemList[i].faceID}-${i}`;
+ : `${itemList[i]}-${i}`;
return (
= ({
>
{!Array.isArray(item) ? (
- {`score ${item.score.toFixed(2)} blur ${item.blur.toFixed(0)}`}
+ {`cluster size ${item.toFixed(2)}`}
) : (
- item.map((faceFN, i) => (
+ item.map((faceWF, i) => (
))
)}
@@ -181,19 +181,20 @@ const ClusterPhotoList: React.FC = ({
);
};
-type ItemListItem = Face | FaceFileNeighbour[];
+// type ItemListItem = Face | FaceFileNeighbour[];
+type ItemListItem = number | ClusterPreviewFaceWF[];
-const itemListFromFaceFNs = (
- faceFNs: FaceFileNeighbours[],
+const itemListFromClusterPreviewWFs = (
+ clusterPreviewWFs: ClusterPreviewWF[],
columns: number,
) => {
const result: ItemListItem[] = [];
- for (let index = 0; index < faceFNs.length; index++) {
- const { face, neighbours } = faceFNs[index];
- result.push(face);
+ for (let index = 0; index < clusterPreviewWFs.length; index++) {
+ const { clusterSize, faces } = clusterPreviewWFs[index];
+ result.push(clusterSize);
let lastIndex = 0;
- while (lastIndex < neighbours.length) {
- result.push(neighbours.slice(lastIndex, lastIndex + columns));
+ while (lastIndex < faces.length) {
+ result.push(faces.slice(lastIndex, lastIndex + columns));
lastIndex += columns;
}
}
@@ -210,12 +211,12 @@ const getShrinkRatio = (width: number, columns: number) =>
(columns * 120);
interface FaceItemProps {
- faceFN: FaceFileNeighbour;
+ faceWF: ClusterPreviewFaceWF;
clusterIDForFaceID: Map;
}
-const FaceItem: React.FC = ({ faceFN, clusterIDForFaceID }) => {
- const { face, enteFile, cosineSimilarity } = faceFN;
+const FaceItem: React.FC = ({ faceWF, clusterIDForFaceID }) => {
+ const { face, enteFile, cosineSimilarity } = faceWF;
const { faceID } = face;
const [objectURL, setObjectURL] = useState();
@@ -252,9 +253,15 @@ const FaceItem: React.FC = ({ faceFN, clusterIDForFaceID }) => {
src={objectURL}
/>
)}
-
- {cosineSimilarity.toFixed(2)}
-
+
+
+ {`${face.blur.toFixed(0)} blr`}
+
+
+
+ {`cos ${cosineSimilarity.toFixed(2)}`}
+
+
);
};
diff --git a/web/packages/new/photos/services/ml/cluster-new.ts b/web/packages/new/photos/services/ml/cluster-new.ts
index 983c128a6a..e2bf78eb35 100644
--- a/web/packages/new/photos/services/ml/cluster-new.ts
+++ b/web/packages/new/photos/services/ml/cluster-new.ts
@@ -352,7 +352,10 @@ export const clusterFacesHdb = async (faceIndexes: FaceIndex[]) => {
const t = Date.now();
// A flattened array of faces.
- const faces0 = [...enumerateFaces(faceIndexes)];
+ // TODO-Cluster ad-hoc filtering and slicing
+ const faces0 = [...enumerateFaces(faceIndexes)]
+ .filter((f) => f.blur > 50)
+ .slice(0, 1000);
// TODO-Cluster testing code, can be removed once done
const faces = Array(1)
.fill(0)
@@ -433,7 +436,7 @@ export const clusterFacesHdb = async (faceIndexes: FaceIndex[]) => {
// Use a higher cosine similarity threshold if either of the two
// faces are blurry.
const threshold =
- existingFace.blur < 100 || newFace.blur < 100 ? 0.84 : 0.7;
+ existingFace.blur < 100 || newFace.blur < 100 ? 0.9 : 0.7;
if (csim > threshold && csim > nnCosineSimilarity) {
nnCluster = existingCluster;
nnCosineSimilarity = csim;
diff --git a/web/packages/new/photos/services/ml/index.ts b/web/packages/new/photos/services/ml/index.ts
index df8d08235c..699a9b9c14 100644
--- a/web/packages/new/photos/services/ml/index.ts
+++ b/web/packages/new/photos/services/ml/index.ts
@@ -366,14 +366,15 @@ export interface ClusterPreviewWF {
faces: ClusterPreviewFaceWF[];
}
-interface ClusterPreviewFaceWF {
+export interface ClusterPreviewFaceWF {
face: Face;
enteFile: EnteFile;
cosineSimilarity: number;
}
export interface ClusterDebugPageContents {
- faceFNs: FaceFileNeighbours[];
+ // faceFNs: FaceFileNeighbours[];
+ clusterPreviewWFs: ClusterPreviewWF[];
clusters: FaceCluster[];
clusterIDForFaceID: Map;
}