# face_recognition Administrator & Developer Guide

## 1. Architecture Overview

`face_recognition` is a Python library and CLI toolkit that provides face detection, facial landmark identification, face encoding, and face comparison. It is a thin, well-designed Python wrapper around dlib's C++-based machine learning models, exposing them through a simple 7-function public API and two Click-based CLI commands.

The library follows a pipeline architecture: images are loaded as numpy arrays, faces are detected using either a HOG or CNN model, facial landmarks are located using a 68-point or 5-point shape predictor, and 128-dimensional face encodings are generated for comparison via euclidean distance.

### Architecture Diagram

```text
┌─────────────────────────────────────────────────────────┐
│                    User Application                      │
│         (Python script / CLI / Web service)               │
├─────────────┬───────────────────────────────┬────────────┤
│  CLI Layer  │        Python API (api.py)     │  Examples  │
│ face_recog  │  load_image_file()             │  webcam    │
│ face_detect │  face_locations()              │  video     │
│  (Click)    │  batch_face_locations()        │  knn       │
│             │  face_landmarks()              │  svm       │
│             │  face_encodings()              │  flask     │
│             │  compare_faces()               │  rpi       │
│             │  face_distance()               │            │
├─────────────┴───────────────────────────────┴────────────┤
│                  dlib (C++ via Python bindings)            │
│  ┌──────────────┐  ┌───────────────┐  ┌────────────────┐ │
│  │ HOG Detector  │  │ CNN Detector   │  │ Shape Predictor│ │
│  │ (CPU-only)    │  │ (CUDA-capable) │  │ (68pt / 5pt)   │ │
│  └──────────────┘  └───────────────┘  ┌────────────────┐ │
│                                        │ Face Encoder   │ │
│                                        │ (128-dim)      │ │
│                                        └────────────────┘ │
├──────────────────────────────────────────────────────────┤
│              face_recognition_models (data)               │
│  pose_predictor_model  │  cnn_face_detector_model         │
│  pose_predictor_5pt    │  face_recognition_model          │
└──────────────────────────────────────────────────────────┘
```

### Component Inventory

| Component | Path | Role |
|---|---|---|
| Public API | `face_recognition/api.py` | 7 public functions + 4 internal helpers |
| Recognition CLI | `face_recognition/face_recognition_cli.py` | `face_recognition` command — match faces against known people |
| Detection CLI | `face_recognition/face_detection_cli.py` | `face_detection` command — locate faces in images |
| Package init | `face_recognition/__init__.py` | Version (`1.4.0`) and public API exports |
| Models data | `face_recognition_models` (separate package) | Pre-trained dlib model files (.dat) |
| Examples | `examples/` | 22 example scripts covering common use cases |
| Tests | `tests/test_face_recognition.py` | unittest-based test suite |
| Docker | `Dockerfile`, `Dockerfile.gpu`, `docker/` | Container builds for CPU and GPU |

### Technology Stack

| Technology | Version | Purpose |
|---|---|---|
| Python | 3.5–3.9 (tested) | Runtime language |
| dlib | >=19.7 | Core ML models (HOG, CNN, shape prediction, face encoding) |
| numpy | any | Image array representation, euclidean distance computation |
| Pillow | any | Image loading and format conversion |
| Click | >=6.0 | CLI command parsing |
| scipy | >=0.17.0 | Used in examples (EAR computation for blink detection) |

> [!NOTE]
> The entire library has zero runtime configuration — no config files, no environment variables, no registry settings. All behavior is controlled through function parameters at call time. The only external dependency that must be present at import time is the `face_recognition_models` package, which provides the pre-trained `.dat` model files.

### Data Flow

```text
Image File/Stream
    │
    ▼
load_image_file() ──→ numpy array (H×W×3 uint8 RGB)
    │
    ▼
face_locations() ──→ list of (top, right, bottom, left) tuples
    │                     │
    │                     ▼
    │              face_landmarks() ──→ list of dicts {feature: [(x,y),...]}
    │                     │
    ▼                     ▼
face_encodings() ──→ list of 128-dim numpy arrays
    │
    ▼
compare_faces() ──→ list of True/False
face_distance()  ──→ numpy array of float distances
```

## 2. System Requirements

### Hardware Requirements

| Resource | Minimum | Recommended | Notes |
|---|---|---|---|
| CPU | x86_64 / ARM | Multi-core x86_64 | HOG model is CPU-bound |
| RAM | 2 GB | 4 GB+ | Large images need more |
| GPU | None (optional) | NVIDIA CUDA-capable | CNN model + batch processing |
| Storage | 100 MB | 500 MB | Models are ~100 MB |

### Software Requirements

| Software | Version | Required? | Notes |
|---|---|---|---|
| Python | 3.5+ | Yes | Tested up to 3.9 per setup.py classifiers |
| C++ compiler | gcc/clang/MSVC | Yes | For dlib compilation |
| CMake | 3.x | Yes | For dlib build |
| CUDA toolkit | 10.x+ | No | For GPU acceleration |
| cuDNN | 7.x+ | No | For GPU acceleration |
| OpenCV | any | No | Only needed for webcam/video examples |

### Docker Images

| Image | Base | Purpose |
|---|---|---|
| `Dockerfile` (root) | Python | CPU-based face_recognition with all dependencies |
| `Dockerfile.gpu` (root) | NVIDIA CUDA | GPU-accelerated face_recognition |
| `docker/cpu/Dockerfile` | Python | CPU variant |
| `docker/gpu/Dockerfile` | NVIDIA CUDA | GPU variant |
| `docker/cpu-jupyter-kubeflow/Dockerfile` | Python + Jupyter | CPU with Jupyter notebook support for Kubeflow |
| `docker/gpu-jupyter-kubeflow/Dockerfile` | NVIDIA CUDA + Jupyter | GPU with Jupyter notebook support for Kubeflow |
| `docker/Dockerfile-python-example` | Python | Example showing Docker usage |

> [!TIP]
> The Kubeflow Dockerfile variants (`cpu-jupyter-kubeflow`, `gpu-jupyter-kubeflow`) include Jupyter notebook support for interactive face recognition experiments in a Kubeflow pipeline.

## 3. Configuration Reference

This library has no configuration files, no environment variables, and no persistent settings. All behavior is controlled through function parameters.

### API Function Parameters — Complete Reference

#### `load_image_file(file, mode='RGB')`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `file` | str or file-like | required | Image path or file object |
| `mode` | str | `'RGB'` | PIL color mode. `'RGB'` for 3-channel, `'L'` for grayscale. Set to `None` to skip conversion. |

Returns: numpy array of shape `(height, width, channels)`.

#### `face_locations(img, number_of_times_to_upsample=1, model="hog")`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `img` | numpy array | required | Image as numpy array |
| `number_of_times_to_upsample` | int | `1` | Upsample count. Higher finds smaller faces. |
| `model` | str | `"hog"` | `"hog"` (CPU, faster) or `"cnn"` (GPU, more accurate) |

Returns: list of `(top, right, bottom, left)` tuples. Coordinates are clamped to image bounds via `_trim_css_to_bounds()`.

#### `batch_face_locations(images, number_of_times_to_upsample=1, batch_size=128)`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `images` | list of numpy arrays | required | List of images |
| `number_of_times_to_upsample` | int | `1` | Upsample count |
| `batch_size` | int | `128` | Images per GPU batch |

Returns: list of lists of `(top, right, bottom, left)` tuples. Always uses CNN model internally.

> [!IMPORTANT]
> `batch_face_locations()` uses `images[0].shape` for bounds trimming on all images in the batch. All images should be the same dimensions for correct coordinate clamping.

#### `face_landmarks(face_image, face_locations=None, model="large")`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `face_image` | numpy array | required | Image to search |
| `face_locations` | list or None | `None` | Pre-computed locations. If `None`, runs face detection first. |
| `model` | str | `"large"` | `"large"` = 68 landmarks, `"small"` = 5 landmarks |

Returns: list of dicts. Large model keys: `chin`, `left_eyebrow`, `right_eyebrow`, `nose_bridge`, `nose_tip`, `left_eye`, `right_eye`, `top_lip`, `bottom_lip`. Small model keys: `nose_tip`, `left_eye`, `right_eye`.

Raises: `ValueError` if model is not `"large"` or `"small"`.

#### `face_encodings(face_image, known_face_locations=None, num_jitters=1, model="small")`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `face_image` | numpy array | required | Image containing faces |
| `known_face_locations` | list or None | `None` | Pre-computed locations |
| `num_jitters` | int | `1` | Re-sampling count. Higher = more accurate, proportionally slower. |
| `model` | str | `"small"` | Landmark model for internal processing |

Returns: list of 128-dimensional numpy arrays.

#### `compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `known_face_encodings` | list | required | List of known 128-d encodings |
| `face_encoding_to_check` | numpy array | required | Single encoding to check |
| `tolerance` | float | `0.6` | Euclidean distance threshold |

Returns: list of `True`/`False` values.

#### `face_distance(face_encodings, face_to_compare)`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `face_encodings` | list | required | List of 128-d encodings |
| `face_to_compare` | numpy array | required | Single encoding |

Returns: numpy array of float distances. Uses `np.linalg.norm(axis=1)` for vectorized euclidean distance. Returns empty array if input list is empty.

### CLI Options — Complete Reference

#### `face_recognition`

```text
Usage: face_recognition [OPTIONS] KNOWN_PEOPLE_FOLDER IMAGE_TO_CHECK
```

| Option | Type | Default | Description |
|---|---|---|---|
| `--cpus` | int | `1` | Parallel CPU cores. `-1` = all. |
| `--tolerance` | float | `0.6` | Match distance threshold |
| `--show-distance` | bool | `False` | Append distance to output |

Output format: `filename,person_name[,distance]`

Special output values: `unknown_person` (no match found), `no_persons_found` (no faces detected).

Images over 1600px are downscaled to 1600x1600 via `PIL.Image.thumbnail()` with `LANCZOS` resampling.

#### `face_detection`

```text
Usage: face_detection [OPTIONS] IMAGE_TO_CHECK
```

| Option | Type | Default | Description |
|---|---|---|---|
| `--cpus` | int | `1` | Parallel CPU cores. `-1` = all. |
| `--model` | str | `"hog"` | `"hog"` or `"cnn"` |
| `--upsample` | int | `0` | Upsample count |

Output format: `filename,top,right,bottom,left`

> [!NOTE]
> Both CLI tools use `forkserver` multiprocessing context on macOS to avoid a crash in libdispatch. This is handled automatically.

## 4. Deployment & Scaling

### Docker Deployment

**CPU container:**

```bash
docker build -t face_recognition -f Dockerfile .
docker run -it --rm -v /path/to/images:/images face_recognition
```

**GPU container (requires NVIDIA Container Toolkit):**

```bash
docker build -t face_recognition:gpu -f Dockerfile.gpu .
docker run -it --rm --runtime=nvidia -v /path/to/images:/images face_recognition:gpu
```

**Docker Compose:**

```yaml
# docker-compose.yml from source
version: '2'
services:
  face_recognition:
    build: .
    volumes:
      - ./:/host
```

> [!WARNING]
> The GPU Dockerfile requires the NVIDIA Container Toolkit installed on the host. Without it, `--runtime=nvidia` will fail. Verify with `docker run --rm --runtime=nvidia nvidia/cuda nvidia-smi`.

### pip Installation for Production

```bash
# Virtual environment recommended
python -m venv face_env
source face_env/bin/activate

# Install with exact dependency versions
pip install face_recognition==1.4.0
pip install face_recognition_models>=0.3.0
```

### Web Service Deployment

The `examples/web_service_example.py` demonstrates a minimal Flask-based face recognition API:

```bash
pip install flask face_recognition
python web_service_example.py
```

```text
 * Running on http://0.0.0.0:5001/ (Press CTRL+C to quit)
```

```bash
curl -XPOST -F "file=@photo.jpg" http://127.0.0.1:5001
```

```json
{
  "face_found_in_image": true,
  "is_picture_of_obama": true
}
```

For production deployment, use a WSGI server (gunicorn, uWSGI) instead of Flask's built-in development server.

### Scaling Considerations

| Strategy | When to Use | How |
|---|---|---|
| Multi-core CLI | Batch processing many files | `--cpus -1` |
| GPU acceleration | High accuracy or batch processing | Compile dlib with CUDA, use `model="cnn"` |
| Frame skipping | Real-time video | Process every Nth frame |
| Resolution reduction | Real-time video | Resize to 1/4 before detection |
| Multiprocessing | Video processing | Dedicated capture/process threads |
| Batch API | GPU with many same-size images | `batch_face_locations()` with `batch_size=128` |

## 5. Operations

### Performance Benchmarking

The library includes a benchmark script at `examples/benchmark.py` that tests each pipeline stage across different image resolutions:

```bash
cd examples
python benchmark.py
```

```text
Benchmarks (Note: All benchmarks are only using a single CPU core)

Timings at 240p:
 - Face locations: 0.0259s (38.61 fps)
 - Face landmarks: 0.0010s (1028.81 fps)
 - Encode face (inc. landmarks): 0.0384s (26.02 fps)
 - End-to-end: 0.0651s (15.36 fps)
```

> [!TIP]
> Face detection is the bottleneck — it gets significantly slower at higher resolutions. For real-time applications, detect faces on a downscaled image and run encoding on the full-resolution crop.

### Performance Optimization Techniques

1. **Reduce input resolution** before face detection:
   ```python
   small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
   ```

2. **Skip frames** in video processing:
   ```python
   process_this_frame = not process_this_frame
   ```

3. **Pre-compute face locations** to avoid redundant detection:
   ```python
   locations = face_recognition.face_locations(image)
   encodings = face_recognition.face_encodings(image, known_face_locations=locations)
   ```

4. **Use the small landmark model** when full 68-point precision isn't needed:
   ```python
   encodings = face_recognition.face_encodings(image, model="small")
   ```

> [!NOTE]
> The `num_jitters` parameter in `face_encodings()` trades speed for accuracy. At `num_jitters=100`, encoding takes 100x longer but produces more stable encodings. The default of `1` is usually sufficient.

### Monitoring

The library produces no logs, no metrics, and no health endpoints. For production monitoring:

- Wrap API calls in timing instrumentation
- Track face detection hit rate (faces found / images processed)
- Monitor encoding distance distributions to detect model degradation
- Watch for `RuntimeError` exceptions from dlib (image format issues, CUDA errors)

## 6. Performance

### Model Comparison

| Model | Speed (CPU) | Speed (GPU) | Accuracy | Best For |
|---|---|---|---|---|
| HOG | Fast | N/A | Good | Real-time CPU applications |
| CNN | Very slow | Fast | Better | Accuracy-critical or GPU-available scenarios |

### Resolution Impact

| Resolution | Face Detection | End-to-End | Recommended For |
|---|---|---|---|
| 240p | ~39 fps | ~15 fps | Raspberry Pi, embedded |
| 480p | ~10 fps | ~5 fps | Webcam applications |
| 720p | ~4 fps | ~2 fps | Video processing |
| 1080p | ~1 fps | ~0.5 fps | Photo analysis only |

### Memory Usage

- Each loaded image: `height × width × 3` bytes (uint8 RGB)
- Each face encoding: 128 × 8 = 1,024 bytes (float64)
- dlib models loaded at import time: ~100 MB resident

## 7. Security

### Input Validation

The library performs minimal input validation:

- `load_image_file()` delegates to PIL, which handles format validation
- `LOAD_TRUNCATED_IMAGES = True` is set at module level, meaning truncated/corrupt images are loaded without error (Pillow fills missing data)
- Face coordinates are clamped to image bounds via `_trim_css_to_bounds()`, preventing out-of-bounds array access
- The CLI tools filter input files by extension (`.jpg`, `.jpeg`, `.png` only via regex)

> [!WARNING]
> The `face_recognition_models` import has a bare `except Exception` handler that calls `quit()` (which raises `SystemExit`). This means a missing models package will terminate the entire Python process, not just raise an importable exception. Issue #1663 identifies this as a design concern. In server applications, catch `SystemExit` or verify the package is installed before importing.

### Denial of Service Considerations

- Very large images consume proportional memory (`H × W × 3` bytes)
- High `number_of_times_to_upsample` values multiply processing time exponentially
- High `num_jitters` values multiply encoding time linearly
- `batch_face_locations()` with large batch sizes can exhaust GPU memory
- No built-in timeouts or resource limits

> [!CAUTION]
> In web-facing applications, validate image dimensions and file size before passing to `face_recognition`. Untrusted users could submit extremely large images to exhaust server memory.

### Dependency Security

| Dependency | Risk | Mitigation |
|---|---|---|
| `dlib` | Native C++ code, compiled from source | Pin version, verify checksums |
| `face_recognition_models` | Binary model files from GitHub | Install from known-good URL |
| `Pillow` | Image parsing (historically vulnerable to crafted files) | Keep updated |
| `numpy` | Native code | Keep updated |
| `pickle` (in KNN example) | Arbitrary code execution on load | Never unpickle untrusted model files |

### Privacy Considerations

- Face encodings are 128-dimensional float vectors that cannot be reversed into face images
- However, encodings can be used to track and identify individuals across images
- The library stores nothing persistently — all state is in-memory
- For GDPR/privacy compliance, treat face encodings as biometric data

## 8. Developer Internals

### Repository Structure

```text
face_recognition/
├── face_recognition/           Core library package
│   ├── __init__.py             Version (1.4.0), public API exports
│   ├── api.py                  7 public functions, 4 internal helpers
│   ├── face_detection_cli.py   face_detection CLI (Click)
│   └── face_recognition_cli.py face_recognition CLI (Click)
├── examples/                   22 example scripts
│   ├── benchmark.py            Performance benchmarking
│   ├── blink_detection.py      Eye blink detection via EAR
│   ├── blur_faces_on_webcam.py Gaussian blur on detected faces
│   ├── digital_makeup.py       Landmark-based digital cosmetics
│   ├── face_distance.py        Distance measurement demo
│   ├── face_recognition_knn.py KNN classifier (scikit-learn)
│   ├── face_recognition_svm.py SVM classifier (scikit-learn)
│   ├── facerec_from_video_file.py Video file processing
│   ├── facerec_from_webcam.py  Basic webcam recognition
│   ├── facerec_from_webcam_faster.py Optimized webcam (1/4 res, skip frames)
│   ├── facerec_from_webcam_multiprocessing.py Multi-process webcam
│   ├── facerec_ipcamera_knn.py IP camera with KNN
│   ├── facerec_on_raspberry_pi.py Raspberry Pi demo
│   ├── find_faces_in_batches.py GPU batch processing
│   ├── find_faces_in_picture.py Basic face detection (HOG)
│   ├── find_faces_in_picture_cnn.py CNN face detection
│   ├── find_facial_features_in_picture.py Landmark visualization
│   ├── identify_and_draw_boxes_on_faces.py Face identification + drawing
│   ├── recognize_faces_in_pictures.py Basic recognition
│   ├── web_service_example.py  Flask web service
│   └── knn_examples/           KNN training/test data
│       ├── train/              Training images (per-person subdirs)
│       └── test/               Test images
├── tests/
│   ├── __init__.py
│   ├── test_face_recognition.py Full test suite
│   └── test_images/            Test fixture images
├── docker/                     Docker configurations
│   ├── cpu/Dockerfile
│   ├── gpu/Dockerfile
│   ├── cpu-jupyter-kubeflow/Dockerfile
│   └── gpu-jupyter-kubeflow/Dockerfile
├── docs/                       Sphinx documentation source
├── Dockerfile                  Root CPU Dockerfile
├── Dockerfile.gpu              Root GPU Dockerfile
├── docker-compose.yml          Docker compose configuration
├── setup.py                    Package build configuration
├── setup.cfg                   Package metadata
├── pyproject.toml              Build system specification
├── requirements.txt            Runtime dependencies
├── requirements_dev.txt        Development dependencies
├── requirements_docs.txt       Documentation build dependencies
├── tox.ini                     Test automation configuration
├── Makefile                    Development convenience targets
├── LICENSE                     MIT license
├── MANIFEST.in                 Source distribution include rules
└── HISTORY.rst                 Changelog
```

### Module Reference

#### `face_recognition/api.py` — Core API

This is the entire functional core of the library. It loads four dlib models at import time and exposes seven public functions.

**Module-level initialization (runs at import time):**

```python
face_detector = dlib.get_frontal_face_detector()                    # HOG detector
pose_predictor_68_point = dlib.shape_predictor(model_68pt_path)     # 68-landmark predictor
pose_predictor_5_point = dlib.shape_predictor(model_5pt_path)       # 5-landmark predictor
cnn_face_detector = dlib.cnn_face_detection_model_v1(cnn_model_path)  # CNN detector
face_encoder = dlib.face_recognition_model_v1(face_rec_model_path) # 128-dim encoder
```

All four models are loaded eagerly. This adds ~1-2 seconds to first import but avoids lazy-loading latency during processing.

**Internal helpers:**

| Function | Purpose |
|---|---|
| `_rect_to_css(rect)` | Convert dlib rect → `(top, right, bottom, left)` tuple |
| `_css_to_rect(css)` | Convert `(top, right, bottom, left)` tuple → dlib rect |
| `_trim_css_to_bounds(css, image_shape)` | Clamp coordinates to image dimensions |
| `_raw_face_locations(img, ...)` | Return raw dlib rect objects (not CSS tuples) |
| `_raw_face_locations_batched(images, ...)` | Batch variant using CNN |
| `_raw_face_landmarks(face_image, ...)` | Return raw dlib shape objects |

**Public API:**

| Function | Lines | Description |
|---|---|---|
| `load_image_file()` | 4 | PIL open → mode convert → numpy array |
| `face_locations()` | 5 | Detect faces, return CSS tuples |
| `batch_face_locations()` | 6 | GPU-batched CNN detection |
| `face_landmarks()` | 25 | Map 68/5 landmark points to named features |
| `face_encodings()` | 3 | Generate 128-dim encoding vectors |
| `compare_faces()` | 2 | Boolean match via distance threshold |
| `face_distance()` | 3 | Vectorized euclidean distance |

#### `face_recognition/face_recognition_cli.py` — Recognition CLI

| Function | Purpose |
|---|---|
| `scan_known_people(folder)` | Load all images in folder, encode faces, use filenames as names |
| `test_image(image, names, encodings, tolerance, show_distance)` | Recognize faces in one image |
| `image_files_in_folder(folder)` | List `.jpg`/`.jpeg`/`.png` files |
| `process_images_in_process_pool(...)` | Multiprocessing wrapper with forkserver |
| `main(...)` | Click command entry point |

Key behavior: images larger than 1600px are thumbnailed to 1600×1600. Unknown faces print `unknown_person`. Images with no detectable faces print `no_persons_found`.

#### `face_recognition/face_detection_cli.py` — Detection CLI

| Function | Purpose |
|---|---|
| `print_result(filename, location)` | Format CSV output |
| `test_image(image, model, upsample)` | Detect faces in one image |
| `image_files_in_folder(folder)` | List image files |
| `process_images_in_process_pool(...)` | Multiprocessing wrapper |
| `main(...)` | Click command entry point |

### Code Patterns and Conventions

**Coordinate system:** All face locations use CSS-style `(top, right, bottom, left)` ordering — not the more common `(x, y, width, height)` or `(top, left, bottom, right)`. This is consistent throughout the API and CLI.

**Image format convention:** All functions expect numpy arrays in RGB color order with uint8 dtype. OpenCV users must convert BGR → RGB before calling any face_recognition function.

**Error handling:** The library uses minimal error handling:
- Module import: bare `except Exception` with `quit()` for missing models
- API functions: no explicit error handling (dlib exceptions propagate)
- `face_landmarks()`: explicit `ValueError` for invalid model names
- CLI: no try/except (crashes propagate to the user)

**Multiprocessing:** Both CLI tools use `forkserver` start method on macOS to work around a libdispatch crash bug. The detection is:
```python
if "forkserver" in multiprocessing.get_all_start_methods():
    context = multiprocessing.get_context("forkserver")
```

**Truncated images:** `ImageFile.LOAD_TRUNCATED_IMAGES = True` is set globally at module level, meaning corrupt/truncated images are silently loaded with missing data filled in by Pillow.

### Testing

The test suite is in `tests/test_face_recognition.py` using Python's `unittest` framework.

**Test categories:**

| Category | Tests | Description |
|---|---|---|
| Image loading | 2 | 8-bit JPG and 32-bit PNG loading |
| Face detection (HOG) | 3 | Single face, partial face, 32-bit image |
| Face detection (CNN) | 2 | CNN model on 8-bit and 32-bit images |
| Batch detection | 2 | Raw and CSS-tuple batched detection |
| Landmarks | 3 | Raw landmarks, large model, small model |
| Encoding | 2 | Default (small) and large model |
| Distance | 2 | Distance computation + empty list handling |
| Comparison | 2 | Face matching + empty list handling |
| CLI (recognition) | 4 | Help, basic, big image, tolerance, show-distance |
| CLI (detection) | 4 | Help, single file, folder, HOG model, CNN model |

**Running tests:**

```bash
# Direct
python -m pytest tests/

# Via tox
tox

# Via make
make test
```

> [!NOTE]
> Tests use fixed test images in `tests/test_images/` with known face positions. The CNN tests use `assertAlmostEqual` with `delta=25` because CNN detection coordinates vary slightly across dlib versions.

**Test dependencies:** `tox`, `flake8`, `click.testing.CliRunner`

### Potential Improvements

1. **Replace `quit()` with proper exception** in `api.py` models import — `quit()` calls `SystemExit`, which is inappropriate in library code (issue #1663)
2. **Add input validation** to public API functions — currently no type checking on `img` parameter
3. **Thread-safe model loading** — dlib models are loaded as module-level globals; concurrent imports in multi-threaded servers could race
4. **Configurable image size limit** for the CLI's 1600px thumbnail threshold
5. **Structured output format** (JSON) option for CLI tools instead of CSV-only
6. **Logging** — the library uses `print()` for warnings instead of Python's `logging` module
7. **Type hints** — no type annotations on any public API function
8. **`batch_face_locations` coordinate bug** — uses `images[0].shape` for bounds trimming on all images in the batch, which is incorrect if images have different dimensions
9. **`LOAD_TRUNCATED_IMAGES` global side effect** — setting this Pillow global affects all PIL usage in the process, not just face_recognition

### Contributing

**Development setup:**

```bash
git clone https://github.com/ageitgey/face_recognition.git
cd face_recognition
pip install -r requirements_dev.txt
pip install -e .
```

**Development dependencies** (`requirements_dev.txt`): `tox`, `flake8`

**Code style:** No enforced formatter. The codebase uses PEP 8-adjacent style with 4-space indentation. `flake8` is configured via `tox.ini`.

**Test workflow:**

```bash
# Lint
flake8 face_recognition tests
# Test
python -m pytest tests/
# Or use tox for full matrix
tox
```

**Build configuration:**

The project uses `setup.py` with `setuptools`:

```python
setup(
    name='face_recognition',
    version='1.4.0',
    packages=['face_recognition'],
    package_data={'face_recognition': ['models/*.dat']},
    entry_points={
        'console_scripts': [
            'face_recognition=face_recognition.face_recognition_cli:main',
            'face_detection=face_recognition.face_detection_cli:main'
        ]
    },
    install_requires=[
        'face_recognition_models>=0.3.0',
        'Click>=6.0',
        'dlib>=19.7',
        'numpy',
        'Pillow'
    ],
)
```

## 9. Integration Points

### Python Library Integration

Import and use the public API directly:

```python
import face_recognition

# All 7 public functions available at package level
face_recognition.load_image_file()
face_recognition.face_locations()
face_recognition.batch_face_locations()
face_recognition.face_landmarks()
face_recognition.face_encodings()
face_recognition.compare_faces()
face_recognition.face_distance()
```

### CLI Integration

Both commands accept files or directories and output CSV to stdout, making them suitable for shell pipelines:

```bash
# Pipe to grep for specific people
face_recognition ./known/ ./photos/ | grep "John"

# Count faces in a directory
face_detection ./photos/ | wc -l

# Process and store results
face_recognition --show-distance 1 ./known/ ./photos/ > results.csv
```

### Flask/Web Integration

The `examples/web_service_example.py` pattern works with any WSGI framework. Key integration points:

- `load_image_file()` accepts file-like objects (e.g., `request.files['file']`)
- All functions are stateless — safe for concurrent requests
- Face encodings are JSON-serializable as lists of floats

### scikit-learn Integration

The KNN and SVM examples demonstrate classifier-based recognition:

- `face_encodings()` output is directly usable as feature vectors for any scikit-learn classifier
- Models can be serialized with `pickle` for persistent storage
- The `image_files_in_folder()` utility from the CLI module is importable for building training sets

### OpenCV Integration

OpenCV provides video capture; face_recognition provides face analysis:

```python
import cv2
import face_recognition

cap = cv2.VideoCapture(0)
ret, frame = cap.read()

# OpenCV BGR → face_recognition RGB
rgb_frame = frame[:, :, ::-1]

# Now use any face_recognition function
locations = face_recognition.face_locations(rgb_frame)
```

> [!IMPORTANT]
> OpenCV uses BGR color order. Always convert to RGB before passing frames to face_recognition functions. Forgetting this conversion is the most common integration mistake and results in degraded accuracy or no faces found.

For basic usage, installation, and getting started, see the User Guide.

---

_Generated May 2026 from ageitgey/face_recognition at 2e2dcce. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
