Files
SnapOtter/packages/ai/python/detect_faces.py
T
Siddharth Kumar Sah 5524939b6f feat: add Phase 4 AI tools with Python bridge and 6 new tools
Add Python bridge (packages/ai/src/bridge.ts) that calls Python scripts
via child_process with venv-first fallback to system python3. Implements
6 AI-powered tools:

- Remove Background: rembg-based with U2-Net/IS-Net models
- Image Upscaling: Real-ESRGAN with Lanczos fallback
- OCR/Text Extraction: Tesseract + PaddleOCR engines
- Face/PII Blur: MediaPipe face detection with configurable blur
- Object Eraser: LaMa inpainting with mask-based input
- Smart Crop: Sharp attention-based entropy cropping (no Python needed)

Each tool includes: Python script, TypeScript wrapper, API route,
and React settings component. All Python scripts handle ImportError
gracefully with clear installation messages.
2026-03-22 04:31:49 +08:00

96 lines
3.0 KiB
Python

"""Face detection and blurring using MediaPipe."""
import sys
import json
def main():
input_path = sys.argv[1]
output_path = sys.argv[2]
settings = json.loads(sys.argv[3]) if len(sys.argv) > 3 else {}
blur_radius = settings.get("blurRadius", 30)
sensitivity = settings.get("sensitivity", 0.5)
try:
from PIL import Image, ImageFilter
img = Image.open(input_path).convert("RGB")
try:
import mediapipe as mp
import numpy as np
mp_face = mp.solutions.face_detection
with mp_face.FaceDetection(
min_detection_confidence=sensitivity
) as detector:
img_array = np.array(img)
results = detector.process(img_array)
faces = []
if results.detections:
for detection in results.detections:
bbox = detection.location_data.relative_bounding_box
x = int(bbox.xmin * img.width)
y = int(bbox.ymin * img.height)
w = int(bbox.width * img.width)
h = int(bbox.height * img.height)
# Add some padding around the face
pad = int(max(w, h) * 0.1)
x1 = max(0, x - pad)
y1 = max(0, y - pad)
x2 = min(img.width, x + w + pad)
y2 = min(img.height, y + h + pad)
face_region = img.crop((x1, y1, x2, y2))
blurred = face_region.filter(
ImageFilter.GaussianBlur(blur_radius)
)
img.paste(blurred, (x1, y1))
faces.append({"x": x, "y": y, "w": w, "h": h})
img.save(output_path)
print(
json.dumps(
{
"success": True,
"facesDetected": len(faces),
"faces": faces,
}
)
)
except ImportError:
# Fallback: no face detection available, save original
img.save(output_path)
print(
json.dumps(
{
"success": True,
"facesDetected": 0,
"faces": [],
"note": "mediapipe not available - no faces detected",
}
)
)
except ImportError:
print(
json.dumps(
{
"success": False,
"error": "Pillow is not installed. Install with: pip install Pillow",
}
)
)
sys.exit(1)
except Exception as e:
print(json.dumps({"success": False, "error": str(e)}))
sys.exit(1)
if __name__ == "__main__":
main()