diff options
author | geireann <geireann.lindfield@gmail.com> | 2024-08-22 13:38:03 -0400 |
---|---|---|
committer | geireann <geireann.lindfield@gmail.com> | 2024-08-22 13:38:03 -0400 |
commit | abac2baf512a545714379fbef3623b46e3be20a8 (patch) | |
tree | 494065508216ac56e706ed60239a4c09a10ca926 | |
parent | a1f90b7c3a99aff9366a353631ea963c778b4740 (diff) |
changes to face recognition to store list of face docs , not descriptors on images.
-rw-r--r-- | src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/search/FaceRecognitionHandler.tsx | 61 |
2 files changed, 26 insertions, 37 deletions
diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx index d1db19e43..46d90db86 100644 --- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx +++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx @@ -80,7 +80,6 @@ export class UniqueFaceView extends ObservableReactComponent<UniqueFaceProps> { // assign the face in the image that's closest to the face collection to be the face that's assigned to the collection if (face_match) { - FaceRecognitionHandler.ImageDocAssociateUniqueFace(imgDoc, face_match, this._props.faceDoc); FaceRecognitionHandler.UniqueFaceAddFaceImage(imgDoc, face_match, this._props.faceDoc); } } @@ -109,7 +108,6 @@ export class UniqueFaceView extends ObservableReactComponent<UniqueFaceProps> { */ removeFaceImageFromUniqueFace = undoable((imgDoc: Doc) => { FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, this._props.faceDoc); - FaceRecognitionHandler.ImageDocDisassociateUniqueFace(imgDoc, this._props.faceDoc); }, 'remove doc from face'); render() { diff --git a/src/client/views/search/FaceRecognitionHandler.tsx b/src/client/views/search/FaceRecognitionHandler.tsx index 487c35d90..f00c3fdf1 100644 --- a/src/client/views/search/FaceRecognitionHandler.tsx +++ b/src/client/views/search/FaceRecognitionHandler.tsx @@ -16,8 +16,7 @@ import { DocumentManager } from '../../util/DocumentManager'; * collection along with the numerical representation of the face, its face descriptor. * * Image Doc's that are added to one or more face collection Docs will be given these metadata fields: - * <image data field>_Face<N> - a numerical representation of the Nth face found in the image - * <image data field>_Faces - a list of all the numerical face representations found in the image. (TODO: this is inelegant as it duplicates each Face<N>) + * <image data field>_faceDescriptors - a list of all the numerical face representations found in the image. * * unique face Doc's are created for each person identified and are stored in the Dashboard's uniqueFaces field * @@ -31,20 +30,34 @@ export class FaceRecognitionHandler { private _loadedModels: boolean = false; private _pendingLoadDocs: Doc[] = []; - private static imgDocFaceField = (imgDoc: Doc, faceDoc: Doc) => `${Doc.LayoutFieldKey(imgDoc)}_${FaceRecognitionHandler.UniqueFaceLabel(faceDoc)}`; + + /** + * return the metadata field name where unique face Docs are stored + * @param imgDoc image with faces + * @returns name of field + */ + private static ImageDocFaceField = (imgDoc: Doc) => `${Doc.LayoutFieldKey(imgDoc)}_faces`; + + /** + * Returns an array of faceDocs for each face recognized in the image + * @param imgDoc image with faces + * @returns faceDoc array + */ + private static ImageDocFaces = (imgDoc: Doc) => DocListCast(imgDoc[`${Doc.LayoutFieldKey(imgDoc)}_faces`]); + /** * initializes an image with an empty list of face descriptors * @param imgDoc image to initialize */ private static initImageDocFaceDescriptors = (imgDoc: Doc) => { - imgDoc[DocData][`${Doc.LayoutFieldKey(imgDoc)}_Faces`] = new List<List<number>>(); + imgDoc[DocData][`${Doc.LayoutFieldKey(imgDoc)}_faceDescriptors`] = new List<List<number>>(); }; /** * returns the face descriptors for each face found on an image Doc * @param imgDoc * @returns list of face descriptors */ - public static ImageDocFaceDescriptors = (imgDoc: Doc) => imgDoc[DocData][`${Doc.LayoutFieldKey(imgDoc)}_Faces`] as List<List<number>>; + public static ImageDocFaceDescriptors = (imgDoc: Doc) => imgDoc[DocData][`${Doc.LayoutFieldKey(imgDoc)}_faceDescriptors`] as List<List<number>>; /** * Adds a face descriptor for a face found in an image @@ -52,34 +65,11 @@ export class FaceRecognitionHandler { * @param faceDescriptor descriptor of a face */ public static ImageDocAddFaceDescriptor = (imgDoc: Doc, faceDescriptor: List<number>) => { - Cast(imgDoc[DocData][`${Doc.LayoutFieldKey(imgDoc)}_Faces`], listSpec('number'), null).push(faceDescriptor as unknown as number); + Cast(imgDoc[DocData][`${Doc.LayoutFieldKey(imgDoc)}_faceDescriptors`], listSpec('number'), null).push(faceDescriptor as unknown as number); }; - /** - * Adds metadata to an image Doc associating it to a unique face that corresponds to a face found in the image - * @param imgDoc image Doc containing faces - * @param faceDescriptor descriptor for the face - * @param faceDoc unique face - */ - public static ImageDocAssociateUniqueFace = (imgDoc: Doc, faceDescriptor: List<number>, faceDoc: Doc) => { - const faceFieldKey = FaceRecognitionHandler.imgDocFaceField(imgDoc, faceDoc); - if (imgDoc[DocData][faceFieldKey]) { - Cast(imgDoc[DocData][faceFieldKey], listSpec('number'), null).push(faceDescriptor as unknown as number); // items are lists of numbers, not numbers, but type system can't handle that - } else { - imgDoc[DocData][faceFieldKey] = new List<List<number>>([faceDescriptor]); - } - }; /** - * Removes metadata from an image Doc to deassociate it from a unique face - * @param imgDoc image Doc containing faces - * @param faceDoc unique face - */ - public static ImageDocDisassociateUniqueFace = (imgDoc: Doc, faceDoc: Doc) => { - const faceFieldKey = FaceRecognitionHandler.imgDocFaceField(imgDoc, faceDoc); - imgDoc[DocData][faceFieldKey] = undefined; - }; - /** * returns a list of all face collection Docs on the current dashboard * @returns face collection Doc list */ @@ -121,17 +111,19 @@ export class FaceRecognitionHandler { public static UniqueFaceAddFaceImage = (img: Doc, faceDescriptor: List<number>, faceDoc: Doc) => { Doc.AddDocToList(faceDoc, 'face_images', img); Cast(faceDoc.face_descriptors, listSpec('number'), null).push(faceDescriptor as unknown as number); // items are lists of numbers, not numbers, but type system can't handle that + Doc.AddDocToList(img[DocData], FaceRecognitionHandler.ImageDocFaceField(img), faceDoc); }; /** * Removes a face from a unique Face Doc, and updates the unique face's set of face image descriptors - * @param imgDoc - image with faces to remove + * @param img - image with faces to remove * @param faceDoc - unique face Doc */ - public static UniqueFaceRemoveFaceImage = (imgDoc: Doc, faceDoc: Doc) => { - Doc.RemoveDocFromList(faceDoc[DocData], 'face_images', imgDoc); - // TODO: remove face descriptor from images' list of face descriptors (below doesn't work) - // faceDoc[DocData].face_descriptors = new List<List<number>>(FaceRecognitionHandler.UniqueFaceDescriptors(faceDoc).filter(fd => !(imgDoc[DocData][FaceRecognitionHandler.imgDocFaceField(imgDoc, faceDoc)] as List<List<number>>).includes(fd))); + public static UniqueFaceRemoveFaceImage = (img: Doc, faceDoc: Doc) => { + Doc.RemoveDocFromList(faceDoc[DocData], 'face_images', img); + const descriptorsEqual = (a:List<number>, b:List<number>) => a === b ? true : a.length === b.length ? a.every((element, index) => element === b[index]) : false; + faceDoc[DocData].face_descriptors = new List<List<number>>(FaceRecognitionHandler.UniqueFaceDescriptors(faceDoc).filter(fd => !FaceRecognitionHandler.ImageDocFaceDescriptors(img).some(desc => descriptorsEqual(fd, desc)))); + Doc.RemoveDocFromList(img[DocData], FaceRecognitionHandler.ImageDocFaceField(img), faceDoc); }; constructor() { @@ -211,7 +203,6 @@ export class FaceRecognitionHandler { const matchedUniqueFace = this.findMatchingFaceDoc(fd.descriptor) ?? this.createUniqueFaceDoc(Doc.ActiveDashboard); // Add image to unique face's image collection, and assign image metadata referencing unique face FaceRecognitionHandler.UniqueFaceAddFaceImage(imgDoc, faceDescriptor, matchedUniqueFace); - FaceRecognitionHandler.ImageDocAssociateUniqueFace(imgDoc, faceDescriptor, matchedUniqueFace); // save the descriptor for the image's list of faces FaceRecognitionHandler.ImageDocAddFaceDescriptor(imgDoc, faceDescriptor); } |