feat: Enhance getSimilar API and UI with excluded faces functionality

This commit updates the `getSimilar` API to include an optional parameter for excluding faces in the results. The Identify component is modified to utilize this new parameter, allowing users to filter out unwanted faces during identification. Additionally, the Help documentation is updated to reflect changes in the identification process, including new filtering options and user instructions for managing excluded faces. Overall, these enhancements improve the user experience and provide more control over face identification.
This commit is contained in:
tanyar09
2025-12-11 13:16:58 -05:00
parent 10f777f3cc
commit bca01a5ac3
5 changed files with 46 additions and 19 deletions
+8 -4
View File
@@ -192,11 +192,15 @@ def get_unidentified_faces(
@router.get("/{face_id}/similar", response_model=SimilarFacesResponse)
def get_similar_faces(face_id: int, db: Session = Depends(get_db)) -> SimilarFacesResponse:
def get_similar_faces(
face_id: int,
include_excluded: bool = Query(False, description="Include excluded faces in results"),
db: Session = Depends(get_db)
) -> SimilarFacesResponse:
"""Return similar unidentified faces for a given face."""
import logging
logger = logging.getLogger(__name__)
logger.info(f"API: get_similar_faces called for face_id={face_id}")
logger.info(f"API: get_similar_faces called for face_id={face_id}, include_excluded={include_excluded}")
# Validate face exists
base = db.query(Face).filter(Face.id == face_id).first()
@@ -204,8 +208,8 @@ def get_similar_faces(face_id: int, db: Session = Depends(get_db)) -> SimilarFac
logger.warning(f"API: Face {face_id} not found")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Face {face_id} not found")
logger.info(f"API: Calling find_similar_faces for face_id={face_id}")
results = find_similar_faces(db, face_id)
logger.info(f"API: Calling find_similar_faces for face_id={face_id}, include_excluded={include_excluded}")
results = find_similar_faces(db, face_id, include_excluded=include_excluded)
logger.info(f"API: find_similar_faces returned {len(results)} results")
items = [
+12 -2
View File
@@ -1512,6 +1512,7 @@ def find_similar_faces(
limit: int = 20000, # Very high default limit - effectively unlimited
tolerance: float = 0.6, # DEFAULT_FACE_TOLERANCE from desktop
filter_frontal_only: bool = False, # New: Only return frontal or tilted faces (not profile)
include_excluded: bool = False, # Include excluded faces in results
) -> List[Tuple[Face, float, float]]: # Returns (face, distance, confidence_pct)
"""Find similar faces matching desktop logic exactly.
@@ -1528,6 +1529,7 @@ def find_similar_faces(
Args:
filter_frontal_only: Only return frontal or tilted faces (not profile)
include_excluded: Include excluded faces in results (default: False)
"""
from src.web.db.models import Photo
@@ -1586,6 +1588,10 @@ def find_similar_faces(
is_unidentified = f.person_id is None
if is_unidentified and confidence_pct >= 40:
# Filter by excluded status if not including excluded faces
if not include_excluded and getattr(f, "excluded", False):
continue
# Filter by pose_mode if requested (only frontal or tilted faces)
if filter_frontal_only and not _is_acceptable_pose_for_auto_match(f.pose_mode):
continue
@@ -1848,9 +1854,11 @@ def find_auto_match_matches(
# Desktop: similar_faces = self.face_processor._get_filtered_similar_faces(
# reference_face_id, tolerance, include_same_photo=False, face_status=None)
# This filters by: person_id is None (unidentified), confidence >= 40%, sorts by distance
# Auto-match always excludes excluded faces
similar_faces = find_similar_faces(
db, reference_face_id, tolerance=tolerance,
filter_frontal_only=filter_frontal_only
filter_frontal_only=filter_frontal_only,
include_excluded=False # Auto-match always excludes excluded faces
)
if similar_faces:
@@ -1994,9 +2002,11 @@ def get_auto_match_person_matches(
return []
# Find similar faces using existing function
# Auto-match always excludes excluded faces
similar_faces = find_similar_faces(
db, reference_face.id, tolerance=tolerance,
filter_frontal_only=filter_frontal_only
filter_frontal_only=filter_frontal_only,
include_excluded=False # Auto-match always excludes excluded faces
)
return similar_faces