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

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, 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.

Stage 2: Confidence Filtering and Person Limit Enforcement

After inference, PoseService._estimate_poses in 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 (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

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:


# 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, 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 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 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. The PoseService enforces this limit during the _estimate_poses method (lines 48-61 in 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 (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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →