File size: 3,632 Bytes
9bc686b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""
Re-enrollment script: Re-generates face embeddings from existing enrolled images
using the current face engine. Run this after upgrading the face engine.

Usage:
    ..\.venv\Scripts\python.exe re_enroll.py
"""
import sys
import os

# Add the backend to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# Set env vars before importing app modules
from dotenv import load_dotenv
load_dotenv()

from app.core.database import SessionLocal
from app.models import models
from app.services.singletons import face_engine
import cv2
import numpy as np
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("ReEnroll")

def re_enroll():
    db = SessionLocal()
    try:
        # Get all employees with images
        employees = db.query(models.Employee).all()
        logger.info(f"Found {len(employees)} employees to re-enroll.")
        
        for employee in employees:
            images = db.query(models.EmployeeImage).filter(
                models.EmployeeImage.employee_id == employee.id
            ).all()
            
            if not images:
                logger.warning(f"No images found for employee {employee.name} ({employee.employee_id})")
                continue
            
            logger.info(f"\nRe-enrolling {employee.name} ({employee.employee_id}) - {len(images)} pose(s)...")
            
            # Delete existing embeddings for this employee
            db.query(models.FaceEmbedding).filter(
                models.FaceEmbedding.employee_id == employee.id
            ).delete()
            db.commit()
            
            re_enrolled_count = 0
            for img_record in images:
                # Read image from disk
                if not os.path.exists(img_record.file_path):
                    logger.warning(f"  Image file not found: {img_record.file_path}")
                    continue
                
                img = cv2.imread(img_record.file_path)
                if img is None:
                    logger.warning(f"  Failed to read image: {img_record.file_path}")
                    continue
                
                # Detect face
                faces = face_engine.detect_faces(img)
                if not faces:
                    logger.warning(f"  No face detected in {img_record.file_path}")
                    continue
                
                face = faces[0]
                
                # Align and extract embedding
                aligned = face_engine.align_face(img, face["landmarks"])
                embedding = face_engine.extract_embedding(aligned)
                embedding_list = embedding.tolist()
                
                # Save new embedding
                new_emb = models.FaceEmbedding(
                    employee_id=employee.id,
                    image_id=img_record.id,
                    embedding=embedding_list
                )
                db.add(new_emb)
                re_enrolled_count += 1
                logger.info(f"  ✓ Re-enrolled pose: {img_record.pose_type}")
            
            db.commit()
            logger.info(f"  Total re-enrolled: {re_enrolled_count}/{len(images)} poses for {employee.name}")
        
        # Final count
        total_embs = db.query(models.FaceEmbedding).count()
        logger.info(f"\n✅ Re-enrollment complete! Total embeddings in DB: {total_embs}")
        
    except Exception as e:
        logger.error(f"Re-enrollment failed: {e}")
        import traceback
        traceback.print_exc()
        db.rollback()
    finally:
        db.close()

if __name__ == "__main__":
    re_enroll()