Temporal Smoothing Techniques for CSI Phase Trajectories in WiFi‑DensePose
WiFi‑DensePose employs three distinct temporal smoothing mechanisms—moving‑average filtering, Butterworth low‑pass filtering, and exponential moving‑average (EMA) on detection confidence—to stabilize noisy CSI phase trajectories before pose estimation.
The ruvnet/wifi-densepose repository processes raw Channel State Information (CSI) through a dedicated sanitization pipeline that applies these temporal smoothing techniques for CSI phase trajectories to suppress high‑frequency jitter while preserving essential motion cues. Understanding these filtering stages is critical for configuring the trade‑off between noise reduction and motion fidelity in dense pose reconstruction systems.
Moving‑Average Smoothing for Phase Trajectories
The first smoothing layer operates inside PhaseSanitizer within v1/src/core/phase_sanitizer.py. The smooth_phase method delegates to _apply_moving_average, which implements a symmetric sliding window mean.
Implementation Details
The method accepts a configurable smoothing_window parameter. If the supplied window size is even, the implementation automatically increments it to the next odd integer, ensuring a symmetric neighborhood around each sample. This prevents phase shifts that would otherwise distort the temporal alignment of the CSI data.
from v1.src.core.phase_sanitizer import PhaseSanitizer
config = {
'unwrapping_method': 'numpy',
'outlier_threshold': 3.0,
'smoothing_window': 5, # Must be odd; auto-corrected if even
'enable_smoothing': True,
'enable_noise_filtering': True,
'noise_threshold': 0.05 # Butterworth cutoff (fraction of Nyquist)
}
sanitizer = PhaseSanitizer(config)
raw_phase = ... # np.ndarray shape (antennas, samples)
clean_phase = sanitizer.sanitize_phase(raw_phase)
Butterworth Low‑Pass Filtering
Following the moving‑average stage, the pipeline applies a 4th‑order Butterworth low‑pass filter via the filter_noise method, which calls _apply_low_pass_filter. This stage targets residual high‑frequency artifacts that survive the initial averaging.
Zero‑Phase Filtering
The cutoff frequency is proportional to the noise_threshold parameter, expressed as a fraction of the Nyquist rate. The implementation uses scipy.signal.filtfilt to apply the filter forward and backward, eliminating group delay and ensuring zero phase distortion. This preserves the temporal alignment of phase trajectories critical for accurate time‑of‑flight calculations.
Exponential Moving Average for Detection Confidence
Beyond the phase trajectory itself, WiFi‑DensePose stabilizes binary human‑presence decisions using an exponential moving‑average (EMA) implemented in v1/src/core/csi_processor.py. The CSIProcessor._apply_temporal_smoothing method smooths scalar confidence scores across successive CSI frames.
EMA Formula and Configuration
The smoothing follows the recurrence relation:
smoothed = α · previous + (1 − α) · raw
Here, α corresponds to the configurable smoothing_factor (typically near 0.9). This technique prevents rapid oscillations between detection states when noise temporarily perturbs the signal energy.
from v1.src.core.csi_processor import CSIProcessor
proc_cfg = {
'sampling_rate': 1000,
'window_size': 256,
'overlap': 0.5,
'noise_threshold': 0.1,
'smoothing_factor': 0.9 # EMA coefficient α
}
processor = CSIProcessor(proc_cfg)
csi_data = ... # CSIData instance
result = await processor.process_csi_data(csi_data)
print(f"Human detected: {result.human_detected}, confidence (smoothed): {result.confidence}")
Configuration and Implementation Examples
All three temporal smoothing techniques for CSI phase trajectories expose hyperparameters through the configuration dictionaries passed to PhaseSanitizer and CSIProcessor. When tuning these values:
- Increase
smoothing_windowto aggressively suppress jitter, but expect increased latency and potential smearing of rapid motion. - Decrease
noise_thresholdto raise the Butterworth cutoff and preserve high‑frequency motion details. - Adjust
smoothing_factorcloser to 1.0 for stronger confidence stabilization, or closer to 0.0 for faster reaction to appearance/disappearance events.
Summary
- Moving‑average smoothing in
v1/src/core/phase_sanitizer.pyapplies a symmetric sliding window mean with automatic odd‑window correction via_apply_moving_average. - Butterworth low‑pass filtering uses a 4th‑order design with
scipy.signal.filtfiltfor zero‑phase distortion, configured bynoise_threshold. - Exponential moving‑average in
v1/src/core/csi_processor.pystabilizes detection confidence scores using_apply_temporal_smoothingwith configurable coefficient α. - These stages execute sequentially within
sanitize_phase()andprocess_csi_data()to yield temporally coherent phase trajectories suitable for dense pose estimation.
Frequently Asked Questions
What is the default window size for moving‑average smoothing in WiFi‑DensePose?
The default configuration typically sets smoothing_window to 5 samples, though the implementation accepts any positive integer. If you supply an even number, the _apply_moving_average method automatically increments it to the nearest odd integer to maintain symmetry.
Why does the Butterworth filter use filtfilt instead of lfilter?
The _apply_low_pass_filter method uses scipy.signal.filtfilt to process the signal both forward and backward. This zero‑phase filtering technique cancels out the group delay inherent in causal IIR filters, ensuring that peaks and troughs in the CSI phase trajectory remain temporally aligned with the original raw data.
How does the EMA smoothing factor affect human detection latency?
A high smoothing_factor (e.g., 0.95) makes the EMA in _apply_temporal_smoothing heavily weight historical confidence values, reducing false‑positive flicker but introducing lag when a human actually enters the scene. Conversely, a low factor (e.g., 0.5) makes the system responsive but more susceptible to noise‑induced state changes.
Can I disable temporal smoothing if I need raw phase data?
Yes. Setting enable_smoothing to False in the PhaseSanitizer configuration skips the moving‑average stage, and setting enable_noise_filtering to False bypasses the Butterworth filter. However, the EMA in CSIProcessor is typically always active unless you modify the source code to skip the _apply_temporal_smoothing call.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →