# Face Filters

## Overview

Face filters act as **quality gates** that skip low-quality detections before running the embedding model. Proper filtering improves both accuracy and performance by avoiding incorrect results (e.g., computing embeddings for non-frontal faces would incorrectly identify them as unknown persons) and reducing unnecessary computation.

### Why Use Filters?

Not every detected face should be processed:

* **Small/distant faces** - Too few pixels for reliable recognition
* **Profile/side views** - Embedding models work best on frontal faces
* **Poor framing** - Faces cut off at edges produce unreliable embeddings
* **Outside region of interest** - Ignore faces in irrelevant areas

Filters improve result quality and prevent wasted compute.

## FaceFilterConfig

All filters are controlled through a `FaceFilterConfig` object:

```python
import degirum_face

filters = degirum_face.FaceFilterConfig(
    # Small face filter
    enable_small_face_filter=True,
    min_face_size=50,
    
    # Zone filter
    enable_zone_filter=True,
    zone=[[100, 100], [500, 100], [500, 400], [100, 400]],
    
    # Geometric filters
    enable_frontal_filter=True,
    enable_shift_filter=True,
)

# Use in configuration
config = degirum_face.FaceRecognizerConfig(
    face_filters=filters,
    # ... other config
)
```

## Filter Types

### 1. Small Face Filter

Skips faces where the bounding box is too small for reliable recognition.

#### Configuration

```python
filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=50  # Minimum pixels for shorter side of bbox
)
```

#### Parameters

* **`enable_small_face_filter`** (bool) - Enable/disable the filter (default: False)
* **`min_face_size`** (int) - Minimum size in pixels for the shorter side of the bounding box (default: 0)

#### When to Use

* Processing images with varying camera distances
* Ignore distant/background people
* Improve accuracy by filtering unreliable small detections
* **Access control systems:** Set `min_face_size` to 2/3 of frame size to trigger recognition only when a person is very close to the camera, eliminating issues with multiple people in frame and ambiguous triggering timing

#### Trade-offs

* **Higher threshold (60-80):** Faster processing, miss distant faces
* **Lower threshold (30-40):** More coverage, slower processing
* **Very high (200-400):** Maximum quality for close-up enrollment (e.g., access control)

#### Example

```python
# Access control - require close-up faces
access_control_filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=200  # ~50% of 400px frame height
)

# General recognition - allow distant faces
general_filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=40
)
```

***

### 2. Zone Filter

Only processes faces within a specified polygon region.

#### Configuration

```python
# Define rectangular zone
zone = [
    [100, 100],   # Top-left corner (x, y)
    [500, 100],   # Top-right corner
    [500, 400],   # Bottom-right corner
    [100, 400]    # Bottom-left corner
]

filters = degirum_face.FaceFilterConfig(
    enable_zone_filter=True,
    zone=zone  # List of [x, y] coordinates (min 3 points)
)
```

#### Parameters

* **`enable_zone_filter`** (bool) - Enable/disable the filter (default: False)
* **`zone`** (list of \[x, y]) - Polygon vertices defining the region of interest. Can be any polygon with 3 or more points (triangle, quadrilateral, pentagon, etc.), not limited to rectangles

#### How It Works

Face center point must be inside the polygon zone. Faces outside are skipped.

#### When to Use

* Focus on specific areas (doorway, checkout counter, entrance)
* Ignore people outside region of interest
* Reduce false positives from background activity

#### Examples

**Rectangular zone:**

```python
# Rectangle from (100,100) to (500,400)
zone = [[100, 100], [500, 100], [500, 400], [100, 400]]
```

**Arbitrary polygon:**

```python
# Pentagonal zone
zone = [[100, 200], [300, 100], [500, 200], [400, 400], [200, 400]]
```

**Entire frame (no filtering):**

```python
# Don't enable zone filter, or use full frame dimensions
zone = [[0, 0], [1920, 0], [1920, 1080], [0, 1080]]
```

***

### 3. Frontal Filter

Only processes faces looking roughly toward the camera (frontal view).

#### Configuration

```python
filters = degirum_face.FaceFilterConfig(
    enable_frontal_filter=True
)
```

#### Parameters

* **`enable_frontal_filter`** (bool) - Enable/disable the filter (default: False)

#### How It Works

Checks if nose keypoint is inside the rectangle formed by eyes and mouth. Profiles/side views fail this test.

#### When to Use

* Need high-quality embeddings (frontal faces work best)
* Access control where users face the camera
* Reduce processing of profile/side views
* Improve recognition accuracy

#### Trade-offs

* **Enabled:** Better quality, miss non-frontal faces
* **Disabled:** Process all angles, lower quality for profiles

#### Example

```python
# Security checkpoint - require frontal faces
security_filters = degirum_face.FaceFilterConfig(
    enable_frontal_filter=True,
    enable_small_face_filter=True,
    min_face_size=150
)

# Photo album - accept all angles
photo_filters = degirum_face.FaceFilterConfig(
    enable_frontal_filter=False,  # Accept profiles
    enable_small_face_filter=True,
    min_face_size=40
)
```

***

### 4. Shift Filter

Skips faces that are poorly framed (cut off at image edges or off-center).

#### Configuration

```python
filters = degirum_face.FaceFilterConfig(
    enable_shift_filter=True
)
```

#### Parameters

* **`enable_shift_filter`** (bool) - Enable/disable the filter (default: False)

#### How It Works

Rejects faces where all 5 facial keypoints are clustered to one side of the bounding box - either all in the left/right half (horizontal) or all in the top/bottom half (vertical). This indicates the face is cut off or poorly framed.

#### When to Use

* Avoid processing partially visible faces
* Improve embedding quality by filtering edge cases
* Video scenarios where people enter/exit frame
* Ensure complete face is visible

#### Trade-offs

* **Enabled:** Higher quality, miss partially visible faces
* **Disabled:** Process all detections, some may be cut off

#### Example

```python
# Video monitoring - skip people entering/exiting
video_filters = degirum_face.FaceFilterConfig(
    enable_shift_filter=True,  # Skip partial faces
    enable_frontal_filter=True,
)

# Static photos - process even if slightly cut off
photo_filters = degirum_face.FaceFilterConfig(
    enable_shift_filter=False,  # Allow edge cases
)
```

***

### 5. ReID Expiration Filter

**Note:** This filter is specific to `FaceTracker` and video tracking workflows. It does not affect `FaceRecognizer` which processes static images.

Reduces embedding extraction frequency using **adaptive exponential backoff** for continuously tracked faces.

#### Configuration

```python
filters = degirum_face.FaceFilterConfig(
    enable_reid_expiration_filter=True,
    reid_expiration_frames=30  # Maximum interval
)
```

#### Parameters

* **`enable_reid_expiration_filter`** (bool) - Enable/disable the ReID expiration filter (default: False)
* **`reid_expiration_frames`** (int) - Maximum interval in frames between embedding extractions for stable tracks (default: 10)

#### How It Works

When enabled, the filter adaptively increases the interval between embedding extractions for continuously tracked faces:

```
Frame 1:  New face → Extract embedding (interval: 1 frame)
Frame 2:  Same face → Extract embedding (interval: 1 frame)
Frame 4:  Same face → Extract embedding (interval: 2 frames)
Frame 8:  Same face → Extract embedding (interval: 4 frames)
Frame 16: Same face → Extract embedding (interval: 8 frames)
Frame 32: Same face → Extract embedding (interval: 16 frames)
Frame 62: Same face → Extract embedding (interval: 30 frames, maxed out at reid_expiration_frames)
Frame 92: Same face → Extract embedding (interval: 30 frames)
...stays at reid_expiration_frames interval
```

**Result:** For a face tracked over 100 frames, extracts \~7 embeddings instead of 100 (14x reduction).

#### When to Use

* Real-time video tracking with `FaceTracker`
* Reduce computational cost for stable, continuously tracked faces
* Maintain accuracy while improving performance

#### Tuning `reid_expiration_frames`

* **Static scenes** (office entry, checkpoint): `reid_expiration_frames=60` - Stable faces, can wait longer between embeddings
* **Dynamic scenes** (retail, crowds): `reid_expiration_frames=15` - Quick movements, need more frequent updates
* **Recommended:** `30` frames (\~1 second at 30 FPS) for balanced performance. Default is `10` frames

#### When Embedding Extraction Happens

* New track detected (first frame)
* Expiration timer reached (adaptive interval: 1, 2, 4, 8... up to max)
* Track ID re-acquired after loss
* Quality filters passed after previous failure

#### Trade-offs

* **Higher value (60+):** Fewer embeddings, faster FPS, slower response to face angle changes
* **Lower value (10-20):** More embeddings, slower FPS, quicker response to movement

#### Example

```python
# Static scene - maximize performance
static_filters = degirum_face.FaceFilterConfig(
    enable_reid_expiration_filter=True,
    reid_expiration_frames=60  # Wait longer between embeddings
)

# Dynamic scene - maintain responsiveness  
dynamic_filters = degirum_face.FaceFilterConfig(
    enable_reid_expiration_filter=True,
    reid_expiration_frames=15  # More frequent updates
)
```

**Important:** This filter only works with `FaceTracker` for continuous video streams. It has no effect on `FaceRecognizer.predict_batch()` since there are no persistent track IDs across batch items.

***

## Combining Filters

Filters work in conjunction - a face must pass **ALL enabled filters** to be processed.

### Strict Filtering

For high-quality, reliable results:

```python
strict_filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=80,              # Larger faces only
    enable_frontal_filter=True,     # Frontal views only
    enable_shift_filter=True,       # Well-framed only
    enable_zone_filter=True,        # Specific area only
    zone=[[200, 150], [600, 150], [600, 450], [200, 450]]
)
```

**Use for:** Access control, security applications, enrollment

### Balanced Filtering

For general use:

```python
balanced_filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=50,              # Moderate size
    enable_frontal_filter=True,     # Prefer frontal
    enable_shift_filter=False,      # Allow some edge cases
)
```

**Use for:** Photo organization, general recognition

### Permissive Filtering

For maximum coverage:

```python
permissive_filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=30,              # Small threshold
    enable_frontal_filter=False,    # All angles
    enable_shift_filter=False,      # All framing
)
```

**Use for:** Photo search, surveillance (wide coverage)

***

## Configuration Methods

### Python Configuration

```python
import degirum_face

filters = degirum_face.FaceFilterConfig(
    enable_frontal_filter=True,
    enable_small_face_filter=True,
    min_face_size=60
)

config = degirum_face.FaceRecognizerConfig(
    face_detection_model_spec=degirum_face.get_face_detection_model_spec("TFLITE/CPU"),
    face_embedding_model_spec=degirum_face.get_face_embedding_model_spec("TFLITE/CPU"),
    db_path="./face_db.lance",
    face_filters=filters,
)
```

***

## Use Case Recommendations

### Access Control / Security

```python
filters = degirum_face.FaceFilterConfig(
    enable_frontal_filter=True,     # Ensure clear view
    enable_small_face_filter=True,
    min_face_size=200,              # Close-up required (~50% frame)
    enable_shift_filter=True,       # Complete face visible
    enable_zone_filter=True,        # Specific entry zone
    zone=[[300, 200], [700, 200], [700, 600], [300, 600]]
)
```

### Video Surveillance

```python
filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=50,               # Moderate distance
    enable_frontal_filter=True,      # Better accuracy
    enable_shift_filter=True,        # Skip entering/exiting
)
```

### Photo Organization

```python
filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=40,               # Allow distant faces
    enable_frontal_filter=False,    # All angles accepted
    enable_shift_filter=False,      # Edge cases OK
)
```

### Maximum Coverage

```python
filters = degirum_face.FaceFilterConfig(
    enable_small_face_filter=True,
    min_face_size=30,               # Very small allowed
    # All geometric filters disabled
)
```

***

## Filter Tuning Guide

1. **Start with balanced defaults:**
   * `min_face_size=50`
   * `enable_frontal_filter=True`
   * Other filters disabled
2. **Test with real data:**
   * Process representative images
   * Check what's being filtered
   * Measure accuracy and performance
3. **Adjust based on results:**
   * **Too many false positives?** Enable more filters or increase thresholds
   * **Missing valid faces?** Relax filters or lower thresholds
   * **Too slow?** Increase `min_face_size` to skip more faces
4. **Consider your use case:**
   * Security: Strict filtering
   * General use: Balanced filtering
   * Search/discovery: Permissive filtering


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.degirum.com/face-recognition/reference/face-filters.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
