From af86f763966bb3e51d6678dcb9f6e39144fa891e Mon Sep 17 00:00:00 2001 From: rahulharpal1603 Date: Tue, 23 Sep 2025 23:24:09 +0530 Subject: [PATCH 1/2] Fix build and lint errors --- backend/app/database/faces.py | 10 +++++-- backend/app/models/FaceDetector.py | 2 +- backend/app/routes/face_clusters.py | 29 ++++++++++++++++--- backend/app/schemas/images.py | 1 + docs/.gitignore | 1 + frontend/package-lock.json | 4 +-- .../src/pages/PersonImages/PersonImages.tsx | 2 +- 7 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 docs/.gitignore diff --git a/backend/app/database/faces.py b/backend/app/database/faces.py index 7e20e8be1..b44438315 100644 --- a/backend/app/database/faces.py +++ b/backend/app/database/faces.py @@ -133,12 +133,14 @@ def db_insert_face_embeddings_by_image_id( image_id, embeddings, confidence, bbox, cluster_id ) + def get_all_face_embeddings(): conn = sqlite3.connect(DATABASE_PATH) cursor = conn.cursor() try: - cursor.execute(""" + cursor.execute( + """ SELECT f.embeddings, f.bbox, @@ -153,7 +155,8 @@ def get_all_face_embeddings(): JOIN images i ON f.image_id=i.id LEFT JOIN image_classes ic ON i.id = ic.image_id LEFT JOIN mappings m ON ic.class_id = m.class_id - """) + """ + ) results = cursor.fetchall() images_dict = {} @@ -173,7 +176,7 @@ def get_all_face_embeddings(): embeddings_json = json.loads(embeddings) bbox_json = json.loads(bbox) except json.JSONDecodeError: - continue; + continue images_dict[image_id] = { "embeddings": embeddings_json, "bbox": bbox_json, @@ -203,6 +206,7 @@ def get_all_face_embeddings(): finally: conn.close() + def db_get_faces_unassigned_clusters() -> List[Dict[str, Union[FaceId, FaceEmbedding]]]: """ Get all faces that don't have assigned clusters. diff --git a/backend/app/models/FaceDetector.py b/backend/app/models/FaceDetector.py index 3f4bb192b..4023447a2 100644 --- a/backend/app/models/FaceDetector.py +++ b/backend/app/models/FaceDetector.py @@ -51,7 +51,7 @@ def detect_faces(self, image_id: str, image_path: str, forSearch: bool = False): embedding = self.facenet.get_embedding(processed_face) embeddings.append(embedding) - if (not forSearch and embeddings): + if not forSearch and embeddings: db_insert_face_embeddings_by_image_id( image_id, embeddings, confidence=confidences, bbox=bboxes ) diff --git a/backend/app/routes/face_clusters.py b/backend/app/routes/face_clusters.py index 731dcbd67..351a7a2f0 100644 --- a/backend/app/routes/face_clusters.py +++ b/backend/app/routes/face_clusters.py @@ -255,21 +255,42 @@ def face_tagging(payload: AddSingleImageRequest): image_id = str(uuid.uuid4()) result = fd.detect_faces(image_id, image_path, forSearch=True) if not result or result["num_faces"] == 0: - return GetAllImagesResponse(success=True, message=f"Successfully retrieved {len(matches)} images", data=[]) + return GetAllImagesResponse( + success=True, + message=f"Successfully retrieved {len(matches)} images", + data=[], + ) process_face = result["processed_faces"][0] new_embedding = fn.get_embedding(process_face) images = get_all_face_embeddings() if len(images) == 0: - return GetAllImagesResponse(success=True, message=f"Successfully retrieved {len(matches)} images", data=[]) + return GetAllImagesResponse( + success=True, + message=f"Successfully retrieved {len(matches)} images", + data=[], + ) else: for image in images: max_similarity = 0 - similarity = FaceNet_util_cosine_similarity(new_embedding, image["embeddings"]) + similarity = FaceNet_util_cosine_similarity( + new_embedding, image["embeddings"] + ) max_similarity = max(max_similarity, similarity) if max_similarity >= CONFIDENCE_PERCENT: - matches.append(ImageData(id=image["id"], path=image["path"], folder_id=image["folder_id"], thumbnailPath=image["thumbnailPath"], metadata=image["metadata"], isTagged=image["isTagged"], tags=image["tags"], bboxes=image["bbox"])) + matches.append( + ImageData( + id=image["id"], + path=image["path"], + folder_id=image["folder_id"], + thumbnailPath=image["thumbnailPath"], + metadata=image["metadata"], + isTagged=image["isTagged"], + tags=image["tags"], + bboxes=image["bbox"], + ) + ) return GetAllImagesResponse( success=True, diff --git a/backend/app/schemas/images.py b/backend/app/schemas/images.py index dba0e3c80..ac1400159 100644 --- a/backend/app/schemas/images.py +++ b/backend/app/schemas/images.py @@ -38,6 +38,7 @@ class FaceTaggingResponse(BaseModel): message: str data: dict + class ImagesResponse(BaseModel): image_files: List[str] folder_path: str diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..88aba5dc1 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +.docs-env/ \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a9e02c437..4f67e67f5 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "PictoPy", - "version": "0.0.1", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "PictoPy", - "version": "0.0.1", + "version": "1.0.0", "dependencies": { "@radix-ui/react-aspect-ratio": "^1.1.7", "@radix-ui/react-avatar": "^1.1.10", diff --git a/frontend/src/pages/PersonImages/PersonImages.tsx b/frontend/src/pages/PersonImages/PersonImages.tsx index 23f860688..9c9bef81d 100644 --- a/frontend/src/pages/PersonImages/PersonImages.tsx +++ b/frontend/src/pages/PersonImages/PersonImages.tsx @@ -113,7 +113,7 @@ export const PersonImages = () => { {/* Media Viewer Modal */} - {isImageViewOpen && } + {isImageViewOpen && } ); }; From c68e405cc6dc3b81e4eba9539e8f365a1e0ea854 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Tue, 23 Sep 2025 23:24:38 +0530 Subject: [PATCH 2/2] Fixed navigation to home --- frontend/src/components/Dialog/FaceSearchDialog.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 17c9073c4..a083a9c66 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -17,10 +17,12 @@ import { hideLoader, showLoader } from '@/features/loaderSlice'; import { usePictoMutation } from '@/hooks/useQueryExtension'; import { fetchSearchedFaces } from '@/api/api-functions'; import { showInfoDialog } from '@/features/infoDialogSlice'; +import { useNavigate } from 'react-router'; +import { ROUTES } from '@/constants/routes'; export function FaceSearchDialog() { const [isDialogOpen, setIsDialogOpen] = useState(false); const { pickSingleFile } = useFile({ title: 'Select File' }); - + const navigate = useNavigate(); const dispatch = useDispatch(); const { mutate: getSearchImages } = usePictoMutation({ @@ -56,6 +58,7 @@ export function FaceSearchDialog() { }); const handlePickFile = async () => { + navigate(`/${ROUTES.HOME}`); setIsDialogOpen(false); const filePath = await pickSingleFile(); if (filePath) {