# How to Integrate Motion Detection with WiFi DensePose: A Complete Implementation Guide

> Learn to integrate motion detection with WiFi DensePose. This guide details how CSI amplitude and antenna correlation enable efficient filtering of static frames for improved pose estimation. Explore the ruvnet/wifi-densepose r...

- Repository: [rUv/wifi-densepose](https://github.com/ruvnet/wifi-densepose)
- Tags: how-to-guide
- Published: 2026-02-19

---

**Motion detection in WiFi DensePose analyzes Channel State Information (CSI) amplitude variance and antenna correlation to generate a motion score that gates DensePose inference, filtering static frames before they reach the pose estimation pipeline.**

WiFi DensePose combines Wi-Fi Channel State Information (CSI) processing with deep-learning pose estimation to track human body positions using only wireless signals. The **motion detection** subsystem operates on the CSI stream before the pose pipeline executes, enabling the system to conserve computational resources and reduce false positives. This guide explains how to integrate and configure motion detection according to the `ruvnet/wifi-densepose` source code architecture.

## How Motion Detection Works in WiFi DensePose

The motion detection system processes raw CSI data to distinguish between static environments and human movement. In [`src/core/csi_processor.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/core/csi_processor.py), the `_analyze_motion_patterns` method combines **amplitude variance** across subcarriers with **antenna correlation** metrics to produce a `motion_score` ranging from 0 to 1.

This score undergoes temporal smoothing via `_apply_temporal_smoothing` using an exponential moving average (EMA), then feeds into `_calculate_detection_confidence` to produce the final confidence value. The **Pose Service** compares this confidence against configurable thresholds to determine whether to invoke the DensePose model or drop the frame.

## Core Architecture and Data Flow

Understanding the component interaction is essential for proper integration. The pipeline flows from hardware abstraction through CSI processing to pose estimation.

### CSI Processor ([`src/core/csi_processor.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/core/csi_processor.py))

The `CSIProcessor` class serves as the primary motion analysis engine. Its `process_csi_data` method executes a multi-stage pipeline:

1. **Pre-processing**: Noise removal, windowing, and amplitude normalization using `csi_noise_threshold`
2. **Feature extraction**: Computes amplitude mean/variance, phase differences, correlation matrices, Doppler shifts, and power spectral density
3. **Motion analysis**: `_analyze_motion_patterns` returns the raw `motion_score`
4. **Human detection**: Aggregates features into a smoothed confidence score wrapped in a `HumanDetectionResult` object

### Pose Service ([`src/services/pose_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/services/pose_service.py))

The `PoseService` orchestrates the full inference pipeline. Its `process_csi_data` method receives the `HumanDetectionResult` containing both `motion_score` and final `confidence` values. The service compares the confidence against `settings.pose_confidence_threshold`:

- **Above threshold**: CSI features pass to the modality translator → DensePose model → pose objects
- **Below threshold**: Frame is dropped or logged without inference

### Hardware Service ([`src/services/hardware_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/services/hardware_service.py))

The `HardwareService` manages router interfaces and feeds raw CSI into the pipeline. It periodically calls `router_interface.get_csi_data()` to obtain `np.ndarray` CSI frames, then forwards them to `PoseService.process_csi_data` along with metadata including timestamps, zone IDs, and SNR values.

### Complete Data Flow

1. **Router** → [`src/hardware/csi_extractor.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/hardware/csi_extractor.py) produces `CSIData` objects with raw amplitude/phase arrays
2. **Hardware Service** converts `CSIData` into NumPy arrays with metadata
3. **Pose Service** invokes `CSIProcessor.process_csi_data()`
4. **Confidence check** against `pose_confidence_threshold` determines DensePose execution
5. **Output**: Pose objects or null result based on motion detection results

## Configuration Parameters for Motion Sensitivity

Fine-tuning motion detection requires adjusting these configuration values in [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py) and `CSIProcessor` initialization:

| Parameter | Location | Default | Effect |
|-----------|----------|---------|--------|
| `csi_noise_threshold` | [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py) | 20.0 dB | Controls noise filtering aggressiveness; higher values zero out more data |
| `human_detection_threshold` | `CSIProcessor.__init__` | 0.8 | Minimum smoothed confidence required to classify a human as present |
| `pose_confidence_threshold` | [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py) | 0.7 | Minimum confidence required to trigger DensePose inference |
| `csi_smoothing_factor` | `CSIProcessor.__init__` | 0.9 | EMA smoothing factor for confidence values; higher values reduce jitter |

Lowering `pose_confidence_threshold` when motion scores are high captures more poses during active movement, while raising it during static periods prevents false detections.

## Implementation Examples

### Basic Pipeline Integration

Initialize the full pipeline and process CSI frames with motion detection:

```python
import asyncio
import numpy as np
from src.services.pose_service import PoseService
from src.config.settings import Settings
from src.config.domains import DomainConfig

async def main():
    # Configure motion detection parameters

    settings = Settings(
        mock_pose_data=False,
        pose_confidence_threshold=0.7,
        mock_hardware=True,
        csi_noise_threshold=20.0,
        csi_smoothing_factor=0.85,
    )
    domain_cfg = DomainConfig()

    # Initialize services

    pose_srv = PoseService(settings, domain_cfg)
    await pose_srv.start()

    # Simulate CSI frame: (subcarriers, antennas, samples)

    mock_csi = np.random.randn(64, 56, 3)
    metadata = {
        "timestamp": asyncio.get_event_loop().time(),
        "zone_ids": ["zone_1"],
        "frequency": 5.0,
        "bandwidth": 20.0,
    }

    # Process with motion detection

    result = await pose_srv.process_csi_data(mock_csi, metadata)
    
    if result["poses"]:
        print(f"Motion score: {result['confidence_scores'][0]:.2f}")
        print(f"Pose confidence: {result['poses'][0]['confidence']:.2f}")
    else:
        print("No motion detected - frame filtered")

    await pose_srv.stop()

asyncio.run(main())

```

### WebSocket Motion Events

Stream motion-aware pose updates to connected clients:

```python
import asyncio
from src.services.pose_service import PoseService
from src.config.settings import Settings
from src.config.domains import DomainConfig

async def stream_motion_events():
    settings = Settings(mock_hardware=True, mock_pose_data=True)
    pose_srv = PoseService(settings, DomainConfig())
    await pose_srv.start()

    async for zone_data in pose_srv.get_current_pose_data():
        for zone_id, payload in zone_data.items():
            # Filter by motion-aware confidence

            if payload["confidence"] > 0.5:
                print(f"[{zone_id}] Motion detected: {payload['pose']['count']} person(s)")
                # Broadcast to WebSocket clients here

        await asyncio.sleep(0.1)

asyncio.run(stream_motion_events())

```

### Dynamic Confidence Thresholding

Adjust sensitivity based on real-time motion scores:

```python
async def adaptive_motion_processing(pose_srv: PoseService):
    while True:
        csi_frame = await acquire_csi()  # Your hardware interface

        metadata = {"zone_ids": ["zone_2"]}
        
        detection = await pose_srv.process_csi_data(csi_frame, metadata)
        motion_score = detection.get("motion_score", 0.0)
        
        # Adapt threshold based on motion intensity

        if motion_score > 0.8:
            pose_srv.settings.pose_confidence_threshold = 0.6
        else:
            pose_srv.settings.pose_confidence_threshold = 0.8
            
        await asyncio.sleep(pose_srv.settings.hardware_polling_interval)

```

## Extending Motion Detection Capabilities

The modular architecture supports several customization patterns:

- **Custom motion classifiers**: Replace `_analyze_motion_patterns` in [`src/core/csi_processor.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/core/csi_processor.py) with Doppler-tracking algorithms or machine-learning classifiers trained on specific movement patterns
- **Multi-zone aggregation**: Leverage `zone_id` metadata from [`hardware_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/hardware_service.py) to compute independent motion scores per spatial zone before aggregation
- **Event hooks**: Implement async callbacks in `HardwareService` or extend `pose_service.get_current_pose_data()` to broadcast WebSocket events when motion transitions from 0 to 1

## Summary

- **Motion detection** operates on CSI amplitude variance and antenna correlation in [`src/core/csi_processor.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/core/csi_processor.py) before DensePose inference occurs
- The `_analyze_motion_patterns` method generates a 0-1 `motion_score` that feeds into confidence calculations via `_apply_temporal_smoothing`
- **Pose Service** gates DensePose execution using `pose_confidence_threshold`, dropping static frames to conserve resources
- Configuration through [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py) enables tuning of noise thresholds, smoothing factors, and confidence levels for specific environments
- Real-time adaptation allows dynamic threshold adjustment based on motion intensity scores

## Frequently Asked Questions

### How is the motion score calculated in WiFi DensePose?

The motion score is calculated in [`src/core/csi_processor.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/core/csi_processor.py) by the `_analyze_motion_patterns` method, which combines amplitude variance across CSI subcarriers with antenna correlation metrics. This raw score is temporally smoothed using an exponential moving average (EMA) with the `csi_smoothing_factor` (default 0.9) to reduce jitter, then normalized to a 0-1 range representing the probability of human movement.

### What configuration settings control motion detection sensitivity?

Four primary settings control sensitivity: `csi_noise_threshold` filters environmental noise in decibels; `human_detection_threshold` (default 0.8) sets the minimum confidence to classify a detection as human; `pose_confidence_threshold` gates DensePose inference; and `csi_smoothing_factor` (default 0.9) determines how aggressively the system smooths confidence values over time. Adjust these in [`src/config/settings.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/config/settings.py) or during `CSIProcessor` initialization.

### Can motion detection be customized for specific environments?

Yes, developers can extend the motion detection system by overriding `_analyze_motion_patterns` with custom logic such as Doppler-based tracking or trained classifiers for specific movement types. The architecture also supports multi-zone awareness by processing `zone_id` metadata from [`src/services/hardware_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/services/hardware_service.py) to compute zone-specific motion scores before aggregation.

### How does motion detection affect DensePose inference performance?

Motion detection significantly improves performance by filtering static frames before they reach the DensePose model. When `HumanDetectionResult.confidence` falls below `pose_confidence_threshold`, the system skips the computationally expensive pose estimation step entirely. This reduces GPU/CPU utilization and latency for scenes with intermittent human presence, as implemented in [`src/services/pose_service.py`](https://github.com/ruvnet/wifi-densepose/blob/main/src/services/pose_service.py).