face/README.md

139 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Genealog Face Service
FastAPI-based face embedding microservice using InsightFace + ONNX Runtime GPU. This service generates face embeddings from images and is designed to be called from the `genealog-api` backend via HTTP.
### Endpoints
- `GET /healthz` basic health check and model info.
- `POST /embed-avatar` JSON body: `{ "image_url": "https://..." }`, returns a single best face embedding for an avatar image.
- `POST /embed-image` JSON body: `{ "image_url": "https://..." }`, returns all detected faces and embeddings.
All embeddings are normalized float vectors suitable for cosine-similarity comparison. Face matching/comparison is handled by the calling service (`genealog-api`).
### Features
- **Async HTTP downloads** with retry logic (httpx + tenacity)
- **Image validation**: size limits (20MB max), dimension limits (32px-8192px), decompression bomb protection
- **Robust image decoding**: handles all color modes (RGB, RGBA, L, LA, PA, CMYK, I, F), EXIF orientation correction
- **Face detection fallback**: If no face is detected in `/embed-avatar`, falls back to center crop embedding
- **Embedding validation**: Checks for NaN/Inf values before returning
- **Modular structure**: Clean separation of concerns (config, models, face processing, image handling, routes)
`/embed-avatar` notes:
- Images are decoded with Pillow and EXIF orientation is applied (e.g. iPhone photos) before running detection.
- If no face is detected, the service will fall back to a center square crop and run the recognition model directly to still produce an embedding. In this case, the `score` field will be `0.0` and `bbox` is the used crop.
### Installation (WSL2, Python venv)
From `/home/hung/genealog-face`:
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
**Dependencies:**
- `fastapi`, `uvicorn` - Web framework
- `insightface` - Face detection and recognition
- `onnxruntime-gpu` - GPU-accelerated inference
- `httpx` - Async HTTP client for image downloads
- `tenacity` - Retry logic
- `opencv-python-headless`, `numpy`, `Pillow` - Image processing
GPU support assumes:
- WSL2 with GPU enabled.
- NVIDIA drivers installed on Windows.
- `nvidia-smi` works inside WSL.
The service uses `insightface` with `CUDAExecutionProvider` first, falling back to CPU if needed.
### Running the service
Use the helper script (recommended):
```bash
cd /home/hung/genealog-face
./run_face_service.sh
```
Defaults:
- Host: `0.0.0.0`
- Port: `18081`
- Model: `buffalo_l`
- Detection size: `1024`
- Workers: `nproc` (all CPU cores detected)
You can override via environment variables:
```bash
PORT=18081 \
FACE_MODEL_NAME=buffalo_l \
FACE_DET_SIZE=1024 \
MAX_DOWNLOAD_SIZE=20971520 \
MAX_IMAGE_DIMENSION=8192 \
DOWNLOAD_TIMEOUT=15.0 \
MAX_RETRIES=3 \
UVICORN_WORKERS=20 \
./run_face_service.sh
```
To run in the background:
```bash
nohup ./run_face_service.sh > face_service.log 2>&1 &
```
Logs are written to `face_service.log` in the repo root.
### Project Structure
```
genealog-face/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app, lifespan handler, health endpoint
│ ├── config.py # Environment variables and constants
│ ├── models.py # Pydantic request/response models
│ ├── face.py # FaceAnalysis loading, embedding logic
│ ├── image.py # Image download, decode, validation
│ └── routes/
│ ├── __init__.py
│ └── embed.py # /embed-avatar, /embed-image endpoints
├── .gitignore
├── requirements.txt
├── run_face_service.sh
└── README.md
```
### Integration with genealog-api (Docker)
The `genealog-api` service expects this face service to be reachable at:
- `FACE_SERVICE_URL: http://host.docker.internal:18081`
You only need to ensure the service is running in WSL on port `18081` before starting the Docker stack.
### Autostart on Windows reboot (via WSL2)
You can have Windows start this service automatically at logon using Task Scheduler:
1. Open **Task Scheduler****Create Task…**.
2. **General** tab:
- Name: `GenealogFaceService`.
- Configure to run for your Windows user.
3. **Triggers** tab:
- New → Begin the task: **At log on**.
4. **Actions** tab:
- Program/script: `wsl.exe`
- Arguments:
```text
-d Ubuntu -- bash -lc "cd /home/hung/genealog-face && nohup ./run_face_service.sh >> face_service.log 2>&1"
```
5. Save the task (provide credentials if prompted).
After this, logging into Windows will start WSL and launch the face service in the background, ready to be used by `genealog-api`.