Face detection/recognition: - Replace YuNet + SFace with InsightFace buffalo_l (RetinaFace + ArcFace) - 512-d ArcFace embeddings (was 128-d SFace), migration 0006 resizes column - Remove YOLO person-bbox workaround — RetinaFace is accurate enough - Detection threshold 0.65 cleanly separates real faces (0.72+) from false positives on dogs/paintings (0.56-0.61) Content-type classification: - CLIP zero-shot classifier using native PyTorch text encoder + ONNX image encoder for high-quality text-image similarity - Categories: photograph, screenshot, document, receipt, meme, artwork - Writes Tag(kind=content_type) per photo via photo_tags - Margin-based confidence: top-1 vs top-2 score difference - New ClassifierSettings in config (enabled, min_confidence) - Wired into vision_fanout pipeline Tested: 6 real faces from 4 photos (zero false positives), 11/13 photos classified (8 photograph, 2 artwork, 1 meme). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
25 lines
981 B
Python
25 lines
981 B
Python
"""
|
|
Face embedding model — stores per-face detection + recognition vectors.
|
|
|
|
cluster_id FKs to tags.id where kind='face_cluster'. Null means
|
|
unclustered (will be assigned by recluster_faces).
|
|
"""
|
|
from sqlalchemy import Column, String, Float, ForeignKey, DateTime, func
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
from pgvector.sqlalchemy import Vector
|
|
import uuid
|
|
|
|
from app.database import Base
|
|
|
|
|
|
class FaceEmbedding(Base):
|
|
__tablename__ = 'face_embeddings'
|
|
|
|
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
|
|
photo_id = Column(String, ForeignKey('photos.id', ondelete='CASCADE'), nullable=False, index=True)
|
|
bbox = Column(JSONB) # [x1, y1, x2, y2] normalized 0-1
|
|
vector = Column(Vector(512)) # ArcFace → 512-d
|
|
cluster_id = Column(String, ForeignKey('tags.id', ondelete='SET NULL'), nullable=True, index=True)
|
|
quality = Column(Float)
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|