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:
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user