Inline and move

This commit is contained in:
Manav Rathi 2024-05-16 12:15:11 +05:30
parent 2a35b0ec9c
commit c48042546e
No known key found for this signature in database
2 changed files with 2 additions and 115 deletions

View file

@ -38,9 +38,9 @@ import arcfaceCropService from "./arcfaceCropService";
import FaceService from "./faceService";
import laplacianBlurDetectionService from "./laplacianBlurDetectionService";
import mobileFaceNetEmbeddingService from "./mobileFaceNetEmbeddingService";
import PeopleService from "./peopleService";
import { fetchImageBitmapForContext } from "../face/image";
import { syncPeopleIndex } from "../face/people";
import yoloFaceDetectionService from "./yoloFaceDetectionService";
/**
@ -628,7 +628,7 @@ class MachineLearningService {
public async syncIndex(syncContext: MLSyncContext) {
await this.getMLLibraryData(syncContext);
await PeopleService.syncPeopleIndex(syncContext);
await syncPeopleIndex(syncContext);
await this.persistMLLibraryData(syncContext);
}

View file

@ -1,113 +0,0 @@
import log from "@/next/log";
import mlIDbStorage from "services/face/db";
import { Face, MLSyncContext, Person } from "services/face/types";
import { fetchImageBitmap, getLocalFile } from "../face/image";
import FaceService, { isDifferentOrOld } from "./faceService";
class PeopleService {
async syncPeopleIndex(syncContext: MLSyncContext) {
const filesVersion = await mlIDbStorage.getIndexVersion("files");
if (
filesVersion <= (await mlIDbStorage.getIndexVersion("people")) &&
!isDifferentOrOld(syncContext.mlLibraryData?.faceClusteringMethod, {
value: "Hdbscan",
version: 1,
})
) {
log.info(
"[MLService] Skipping people index as already synced to latest version",
);
return;
}
// TODO: have faces addresable through fileId + faceId
// to avoid index based addressing, which is prone to wrong results
// one way could be to match nearest face within threshold in the file
const allFacesMap = await FaceService.getAllSyncedFacesMap(syncContext);
const allFaces = getAllFacesFromMap(allFacesMap);
await FaceService.runFaceClustering(syncContext, allFaces);
await this.syncPeopleFromClusters(syncContext, allFacesMap, allFaces);
await mlIDbStorage.setIndexVersion("people", filesVersion);
}
private async syncPeopleFromClusters(
syncContext: MLSyncContext,
allFacesMap: Map<number, Array<Face>>,
allFaces: Array<Face>,
) {
const clusters =
syncContext.mlLibraryData.faceClusteringResults?.clusters;
if (!clusters || clusters.length < 1) {
return;
}
for (const face of allFaces) {
face.personId = undefined;
}
await mlIDbStorage.clearAllPeople();
for (const [index, cluster] of clusters.entries()) {
const faces = cluster.map((f) => allFaces[f]).filter((f) => f);
// TODO: take default display face from last leaves of hdbscan clusters
const personFace = findFirstIfSorted(
faces,
(a, b) => b.detection.probability - a.detection.probability,
);
if (personFace && !personFace.crop?.cacheKey) {
const file = await getLocalFile(personFace.fileId);
const imageBitmap = await fetchImageBitmap(file);
await FaceService.saveFaceCrop(
imageBitmap,
personFace,
syncContext,
);
}
const person: Person = {
id: index,
files: faces.map((f) => f.fileId),
displayFaceId: personFace?.id,
faceCropCacheKey: personFace?.crop?.cacheKey,
};
await mlIDbStorage.putPerson(person);
faces.forEach((face) => {
face.personId = person.id;
});
// log.info("Creating person: ", person, faces);
}
await mlIDbStorage.updateFaces(allFacesMap);
}
}
export default new PeopleService();
function findFirstIfSorted<T>(
elements: Array<T>,
comparator: (a: T, b: T) => number,
) {
if (!elements || elements.length < 1) {
return;
}
let first = elements[0];
for (let i = 1; i < elements.length; i++) {
const comp = comparator(elements[i], first);
if (comp < 0) {
first = elements[i];
}
}
return first;
}
function getAllFacesFromMap(allFacesMap: Map<number, Array<Face>>) {
const allFaces = [...allFacesMap.values()].flat();
return allFaces;
}