# How Multi-Person Tracking Works in WiFi-DensePose: A Technical Deep Dive

> Discover how WiFi-DensePose tracks multiple people. Learn about its three-stage pipeline: CSI processing, individual detection, filtering, and spatial zone assignment. Get the technical details.

- Repository: [rUv/wifi-densepose](https://github.com/ruvnet/wifi-densepose)
- Tags: deep-dive
- Published: 2026-02-16

---

**WiFi-DensePose performs multi-person tracking by processing Wi-Fi Channel State Information (CSI) through a three-stage pipeline that detects individuals per frame, filters by confidence thresholds, and assigns spatial zones based on bounding box centers.**

The `ruvnet/wifi-densepose` repository implements a novel approach to human pose estimation using Wi-Fi signals rather than cameras. Understanding how the system handles **multi-person tracking** is essential for deploying occupancy analytics, activity recognition, or zone-based monitoring in smart building applications.

## The Three-Stage Multi-Person Tracking Pipeline

The system processes each incoming CSI frame through a coordinated sequence of neural network inference, confidence filtering, and spatial mapping.

### Stage 1: Per-Frame Pose Estimation with DensePoseHead

The core detection logic resides in [`src/models/densepose_head.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/models/densepose_head.py), where the `DensePoseHead` model analyzes Wi-Fi CSI tensors to identify human shapes. For each frame, the model outputs a list of person detections containing:

- **Bounding boxes** defining spatial extent
- **Confidence scores** indicating detection reliability
- **Keypoint coordinates** for pose estimation
- **Activity labels** for behavior classification

The model returns detections in the standard format used throughout the service, as implemented in lines 31-84 of [`src/models/densepose_head.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/models/densepose_head.py).

### Stage 2: Confidence Filtering and Person Limit Enforcement

After inference, `PoseService._estimate_poses` in [`src/services/pose_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/services/pose_service.py) (lines 48-61) applies two critical constraints to ensure reliable **multi-person tracking**:

1. **Confidence thresholding**: Detections below `settings.pose_confidence_threshold` are discarded as noise
2. **Person limit capping**: The system enforces `settings.pose_max_persons` to prevent resource exhaustion and maintain real-time performance

This filtering ensures that only high-probability human detections proceed to zone assignment, reducing false positives in crowded environments.

### Stage 3: Spatial Zone Assignment

The final stage maps detected individuals to predefined spatial zones for occupancy analytics. While the production system uses a zone manager, the integration tests in [`v1/tests/integration/test_pose_pipeline.py`](https://github.com/ruvnet/wifi-densepose/blob/main/v1/tests/integration/test_pose_pipeline.py) (lines 54-71) demonstrate the exact algorithm via `MockZoneManager.assign_persons_to_zones`:

- Calculate the center point of each person's bounding box
- Compare the center against rectangular zone boundaries
- Assign the `zone_id` of the containing region
- Update per-zone occupancy counts

The result is a structured output containing both individual tracking data and aggregate zone statistics.

## Implementation Details and Code Examples

The `PoseService.estimate_poses` method returns a dictionary with two essential keys for **multi-person tracking**:

- `"persons"`: A list of detected individuals with `person_id`, `confidence`, `bounding_box`, and `zone_id`
- `"zone_summary"`: A mapping of `zone_id` to occupancy counts for real-time space utilization metrics

### Running Inference and Inspecting Multi-Person Data

```python
import asyncio
import numpy as np
from src.services.pose_service import PoseService
from src.config.settings import get_settings

async def demo_multi_person_tracking():
    settings = get_settings()
    service = PoseService(settings, domain_config=None)
    await service.start()

    # Mock CSI frame simulating Wi-Fi signal data

    mock_csi = np.random.randn(64, 56, 3)
    metadata = {"zone_ids": ["zone_1", "zone_2"]}

    result = await service.estimate_poses(
        zone_ids=metadata["zone_ids"],
        confidence_threshold=0.4,
        max_persons=8,
        include_keypoints=True
    )

    print(f"Detected persons: {len(result['persons'])}")
    for person in result["persons"]:
        print(f"- ID {person['person_id']}: "
              f"conf={person['confidence']:.2f}, "
              f"zone={person.get('zone_id')}")

    print("Zone occupancy:", result["zone_summary"])

asyncio.run(demo_multi_person_tracking())

```

### Streaming Zone-Grouped Pose Data

For real-time applications, the service provides zone-grouped output suitable for WebSocket transmission:

```python

# Inside a WebSocket handler (see src/services/pose_service.py lines 84-107)

async for frame in websocket:
    zone_data = await pose_service.get_current_pose_data()
    await websocket.send_json(zone_data)

```

## Key Configuration Parameters for Multi-Person Tracking

The system's behavior is controlled through [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py), which exposes these critical parameters:

- **`pose_confidence_threshold`**: Minimum detection confidence (0.0-1.0) required to include a person in tracking results
- **`pose_max_persons`**: Hard limit on simultaneous tracked individuals to ensure computational resources remain available for real-time processing
- **Zone definitions**: Spatial boundaries configured via `domain_config` that determine how bounding box centers map to logical areas

## Summary

WiFi-DensePose implements **multi-person tracking** through a robust three-stage architecture:

- **DensePoseHead** in [`src/models/densepose_head.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/models/densepose_head.py) performs per-frame pose estimation from Wi-Fi CSI data
- **PoseService** filters detections by confidence thresholds and enforces person limits via `settings.pose_confidence_threshold` and `settings.pose_max_persons`
- **Zone assignment** algorithms map detected individuals to spatial regions by calculating bounding box centers against predefined zone boundaries

The system outputs structured data containing both individual person tracks and aggregate zone occupancy statistics, enabling real-time monitoring applications without camera-based privacy concerns.

## Frequently Asked Questions

### How does WiFi-DensePose handle occlusions in multi-person tracking?

The system relies on Wi-Fi Channel State Information rather than visual cameras, meaning it does not experience traditional visual occlusions where one person blocks another from a camera's view. However, when Wi-Fi signals from multiple people create interference or overlapping signatures, the **DensePoseHead** model in [`src/models/densepose_head.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/models/densepose_head.py) attempts to disambiguate individuals based on spatial separation in the CSI domain. The confidence filtering stage then removes uncertain detections that fall below `settings.pose_confidence_threshold`.

### What is the maximum number of people the system can track simultaneously?

The maximum number of tracked individuals is configurable via `settings.pose_max_persons` in [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py). The **PoseService** enforces this limit during the `_estimate_poses` method (lines 48-61 in [`src/services/pose_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/services/pose_service.py)) by truncating the detection list after sorting by confidence score. While the theoretical limit depends on computational resources and Wi-Fi channel capacity, the default configuration typically supports 8-10 people for real-time performance.

### How does zone assignment work in the DensePose system?

Zone assignment maps detected persons to logical spatial regions using geometric containment tests. As demonstrated in [`v1/tests/integration/test_pose_pipeline.py`](https://github.com/ruvnet/wifi-densepose/blob/main/v1/tests/integration/test_pose_pipeline.py) (lines 54-71), the algorithm calculates the center point of each person's bounding box and checks which predefined rectangular zone contains that point. The **MockZoneManager** assigns the corresponding `zone_id` to the person record and updates the `zone_summary` counts. This enables occupancy analytics without requiring precise coordinate tracking.

### Can WiFi-DensePose track people across multiple rooms?

The system can track people across multiple rooms provided that the Wi-Fi CSI coverage extends to those areas and each room is defined as a distinct zone in the configuration. The **PoseService** accepts a list of `zone_ids` during inference (as shown in the code example), allowing the system to categorize detections by room. However, the current implementation processes each CSI frame independently without explicit cross-frame identity matching (re-identification), meaning it tracks "person instances" rather than maintaining persistent identities across time as individuals move between rooms.