-
-
Notifications
You must be signed in to change notification settings - Fork 620
feat: WebCam feature #583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: WebCam feature #583
Changes from 31 commits
8b2c12b
0129f7c
52a8a57
7b73b34
4fc47c7
5c05baf
1e4b900
5d06b19
b9a36dd
2c037c8
79c9b67
f655d50
994b943
ed5168b
b083616
4fba2f2
ec95615
14f55fc
efe79db
fd18420
dbc0820
5b216a6
1f7113d
eb99b0e
7c8bef7
7297b59
a12a7c9
340b1e9
aed41b4
aa01490
8967c03
e74e37e
06f3c53
66b22a5
7c3eeb0
f7c4a97
ac41b8b
8a1a930
8d7a082
e39321e
6fbb39d
d1c9131
acadd54
5372fbe
19d11d3
2dfa314
73278fc
df38c90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| import uuid | ||
| from typing import Optional, List, Dict, Any | ||
| from pydantic import BaseModel | ||
| from app.config.settings import CONFIDENCE_PERCENT, DEFAULT_FACENET_MODEL | ||
| from app.database.faces import get_all_face_embeddings | ||
| from app.models.FaceDetector import FaceDetector | ||
| from app.models.FaceNet import FaceNet | ||
| from app.utils.FaceNet import FaceNet_util_cosine_similarity | ||
|
|
||
|
|
||
| class BoundingBox(BaseModel): | ||
| x: float | ||
| y: float | ||
| width: float | ||
| height: float | ||
|
|
||
|
|
||
| class ImageData(BaseModel): | ||
| id: str | ||
| path: str | ||
| folder_id: str | ||
| thumbnailPath: str | ||
| metadata: Dict[str, Any] | ||
| isTagged: bool | ||
| tags: Optional[List[str]] = None | ||
| bboxes: BoundingBox | ||
|
|
||
|
|
||
| class GetAllImagesResponse(BaseModel): | ||
| success: bool | ||
| message: str | ||
| data: List[ImageData] | ||
|
Comment on lines
+11
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eliminate duplicate model definitions. The Move these models to a shared location (e.g., -from typing import Optional, List, Dict, Any
-from pydantic import BaseModel
+from app.schemas.face_search import BoundingBox, ImageData, GetAllImagesResponse
from app.config.settings import CONFIDENCE_PERCENT, DEFAULT_FACENET_MODEL
from app.database.faces import get_all_face_embeddings
from app.models.FaceDetector import FaceDetector
from app.models.FaceNet import FaceNet
from app.utils.FaceNet import FaceNet_util_cosine_similarity
-
-
-class BoundingBox(BaseModel):
- x: float
- y: float
- width: float
- height: float
-
-
-class ImageData(BaseModel):
- id: str
- path: str
- folder_id: str
- thumbnailPath: str
- metadata: Dict[str, Any]
- isTagged: bool
- tags: Optional[List[str]] = None
- bboxes: BoundingBox
-
-
-class GetAllImagesResponse(BaseModel):
- success: bool
- message: str
- data: List[ImageData]Then update
|
||
|
|
||
|
|
||
| def perform_face_search(image_path: str) -> GetAllImagesResponse: | ||
| """ | ||
| Performs face detection, embedding generation, and similarity search. | ||
|
|
||
| Args: | ||
| image_path (str): Path to the image file to process. | ||
|
|
||
| Returns: | ||
| GetAllImagesResponse: Search result containing matched images. | ||
| """ | ||
| fd = FaceDetector() | ||
| fn = FaceNet(DEFAULT_FACENET_MODEL) | ||
|
|
||
| try: | ||
| matches = [] | ||
| image_id = str(uuid.uuid4()) | ||
|
|
||
| try: | ||
| result = fd.detect_faces(image_id, image_path, forSearch=True) | ||
| except Exception as e: | ||
| return GetAllImagesResponse( | ||
| success=False, | ||
| message=f"Failed to process image: {str(e)}", | ||
| data=[], | ||
| ) | ||
| if not result or result["num_faces"] == 0: | ||
| return GetAllImagesResponse( | ||
| success=True, | ||
| message="No faces detected in the image.", | ||
| data=[], | ||
| ) | ||
|
Comment on lines
+48
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Add error handling for image loading and detection failures. The function does not handle potential failures such as:
Without explicit error handling, exceptions will propagate to the caller with potentially unclear error messages. Wrap the detection logic in a try-except block: try:
matches = []
image_id = str(uuid.uuid4())
- result = fd.detect_faces(image_id, image_path, forSearch=True)
+ try:
+ result = fd.detect_faces(image_id, image_path, forSearch=True)
+ except Exception as e:
+ return GetAllImagesResponse(
+ success=False,
+ message=f"Failed to process image: {str(e)}",
+ data=[],
+ )
+
if not result or result["num_faces"] == 0:
return GetAllImagesResponse(
success=True,
message="No faces detected in the image.",
data=[],
)Also consider validating that import os
if not os.path.exists(image_path):
return GetAllImagesResponse(
success=False,
message="Image file not found.",
data=[],
)🤖 Prompt for AI Agents |
||
|
|
||
| process_face = result["processed_faces"][0] | ||
| new_embedding = fn.get_embedding(process_face) | ||
|
|
||
| images = get_all_face_embeddings() | ||
| if not images: | ||
| return GetAllImagesResponse( | ||
| success=True, | ||
| message="No face embeddings available for comparison.", | ||
| data=[], | ||
| ) | ||
|
|
||
| for image in images: | ||
| similarity = FaceNet_util_cosine_similarity( | ||
| new_embedding, image["embeddings"] | ||
| ) | ||
| if 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"], | ||
| ) | ||
| ) | ||
|
|
||
| return GetAllImagesResponse( | ||
| success=True, | ||
| message=f"Successfully retrieved {len(matches)} matching images.", | ||
| data=matches, | ||
| ) | ||
|
|
||
| finally: | ||
| if "fd" in locals() and fd is not None: | ||
| fd.close() | ||
| if "fn" in locals() and fn is not None: | ||
| fn.close() | ||
Uh oh!
There was an error while loading. Please reload this page.