101
scripts/backfill_face_recognition.py
Executable file
101
scripts/backfill_face_recognition.py
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Backfill face recognition scan results for existing files
|
||||
|
||||
This script looks at existing downloads and infers face recognition results:
|
||||
- status='completed' and file in final destination = matched
|
||||
- status='review' and file in review queue = no match
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from modules.unified_database import UnifiedDatabase
|
||||
from pathlib import Path
|
||||
|
||||
def backfill_face_recognition():
|
||||
"""Backfill face recognition results from existing downloads"""
|
||||
|
||||
db = UnifiedDatabase()
|
||||
|
||||
print("🔄 Backfilling face recognition scan results...")
|
||||
print("=" * 70)
|
||||
|
||||
with db.get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Get all downloads with file paths
|
||||
cursor.execute('''
|
||||
SELECT id, filename, file_path, status
|
||||
FROM downloads
|
||||
WHERE file_path IS NOT NULL AND file_path != ''
|
||||
''')
|
||||
|
||||
downloads = cursor.fetchall()
|
||||
|
||||
matched_count = 0
|
||||
no_match_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
for download in downloads:
|
||||
download_id = download['id']
|
||||
filename = download['filename']
|
||||
file_path = download['file_path']
|
||||
status = download['status']
|
||||
|
||||
# Check if already scanned
|
||||
cursor.execute('''
|
||||
SELECT id FROM face_recognition_scans
|
||||
WHERE file_path = ?
|
||||
''', (file_path,))
|
||||
|
||||
if cursor.fetchone():
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# Determine if file is image/video
|
||||
path = Path(file_path)
|
||||
ext = path.suffix.lower()
|
||||
image_exts = {'.jpg', '.jpeg', '.png', '.gif', '.heic', '.heif'}
|
||||
video_exts = {'.mp4', '.mov', '.webm', '.avi', '.mkv', '.flv', '.m4v'}
|
||||
|
||||
if ext not in (image_exts | video_exts):
|
||||
continue # Skip non-media files
|
||||
|
||||
# Infer face recognition result from status
|
||||
if status == 'review':
|
||||
# File in review = no match
|
||||
has_match = False
|
||||
matched_person = None
|
||||
confidence = 0.0 # No match = 0% confidence
|
||||
no_match_count += 1
|
||||
elif status == 'completed' and '/review' not in file_path:
|
||||
# File in final destination = matched (assume Eva Longoria for now)
|
||||
has_match = True
|
||||
matched_person = 'Eva Longoria'
|
||||
confidence = 1.0 # Backfill assumes 100% for approved files
|
||||
matched_count += 1
|
||||
else:
|
||||
continue # Skip uncertain cases
|
||||
|
||||
# Insert retroactive scan result
|
||||
cursor.execute('''
|
||||
INSERT INTO face_recognition_scans
|
||||
(download_id, file_path, has_match, matched_person, confidence, face_count, scan_type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
''', (download_id, file_path, has_match, matched_person, confidence, 0, 'backfill'))
|
||||
|
||||
conn.commit()
|
||||
|
||||
print()
|
||||
print("✅ Backfill complete!")
|
||||
print(f" Matched: {matched_count}")
|
||||
print(f" No match: {no_match_count}")
|
||||
print(f" Skipped (already scanned): {skipped_count}")
|
||||
print("=" * 70)
|
||||
|
||||
db.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
backfill_face_recognition()
|
||||
Reference in New Issue
Block a user