add data denoising
This commit is contained in:
parent
af9faa3d07
commit
d15b82f031
@ -43,8 +43,8 @@ class CSIHeader:
|
|||||||
self.num_rx = data[46]
|
self.num_rx = data[46]
|
||||||
self.num_tx = data[47]
|
self.num_tx = data[47]
|
||||||
self.num_subcarriers = struct.unpack("I", data[52:56])[0]
|
self.num_subcarriers = struct.unpack("I", data[52:56])[0]
|
||||||
self.rssi1 = struct.unpack("I", data[60:64])[0]
|
self.rssi1: int = struct.unpack("I", data[60:64])[0]
|
||||||
self.rssi2 = struct.unpack("I", data[64:68])[0]
|
self.rssi2: int = struct.unpack("I", data[64:68])[0]
|
||||||
self.source_mac = struct.unpack("BBBBBB", data[68:74])
|
self.source_mac = struct.unpack("BBBBBB", data[68:74])
|
||||||
self.source_mac_string = "%02x:%02x:%02x:%02x:%02x:%02x" % struct.unpack(
|
self.source_mac_string = "%02x:%02x:%02x:%02x:%02x:%02x" % struct.unpack(
|
||||||
"BBBBBB", data[68:74]
|
"BBBBBB", data[68:74]
|
||||||
|
|||||||
@ -18,6 +18,8 @@ class Preprocessing(BaseModel):
|
|||||||
|
|
||||||
bandpass: Bandpass
|
bandpass: Bandpass
|
||||||
subcarrier_step: int
|
subcarrier_step: int
|
||||||
|
denoising: Literal["none", "median", "mean"] = "median"
|
||||||
|
denoising_period: float = 1
|
||||||
|
|
||||||
|
|
||||||
class MUSIC(BaseModel):
|
class MUSIC(BaseModel):
|
||||||
@ -36,6 +38,10 @@ class Antennas(BaseModel):
|
|||||||
spacing: float
|
spacing: float
|
||||||
order: list[tuple[Host, int]]
|
order: list[tuple[Host, int]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def count(self) -> int:
|
||||||
|
return len(self.order)
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseModel):
|
class Config(BaseModel):
|
||||||
receive_hosts: list[Host]
|
receive_hosts: list[Host]
|
||||||
@ -66,6 +72,10 @@ class Config(BaseModel):
|
|||||||
return "6"
|
return "6"
|
||||||
raise ValueError(f"{self.central_freq} is not a valid Wi-Fi channel")
|
raise ValueError(f"{self.central_freq} is not a valid Wi-Fi channel")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def subcarriers(self) -> int:
|
||||||
|
return int((self.channel_width * 1e6) // self.delta_f) - 8
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def delta_f(self) -> int:
|
def delta_f(self) -> int:
|
||||||
if self.frame_format == "HESU":
|
if self.frame_format == "HESU":
|
||||||
|
|||||||
@ -7,8 +7,10 @@ import numpy.typing as npt
|
|||||||
from scipy.signal import butter, correlate, sosfilt, sosfilt_zi
|
from scipy.signal import butter, correlate, sosfilt, sosfilt_zi
|
||||||
|
|
||||||
from where_fi.collection import CSIMatrix
|
from where_fi.collection import CSIMatrix
|
||||||
|
from where_fi.collection.csi_frame import CSI
|
||||||
|
from where_fi.collection.protocols import CSIHost
|
||||||
|
from where_fi.config import config
|
||||||
|
|
||||||
from ..config import config
|
|
||||||
from ..visualise import server as visualise
|
from ..visualise import server as visualise
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -28,13 +30,41 @@ class Preprocessor:
|
|||||||
# output="sos",
|
# output="sos",
|
||||||
# )
|
# )
|
||||||
self._last_sample = None
|
self._last_sample = None
|
||||||
|
self.denoising_samples = int(
|
||||||
|
config.preprocessing.denoising_period * config.collection_sample_rate
|
||||||
|
)
|
||||||
|
self.circular_buffer = np.zeros(
|
||||||
|
(
|
||||||
|
self.denoising_samples, # Number of samples
|
||||||
|
config.subcarriers, # Number of subcarriers
|
||||||
|
config.antennas.count, # Number of RX antennas
|
||||||
|
1, # Number of TX antennas
|
||||||
|
),
|
||||||
|
dtype=np.complex64,
|
||||||
|
)
|
||||||
|
self.sample_index = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def last_sample(self) -> None | CSIMatrix:
|
def last_sample(self) -> None | CSIMatrix:
|
||||||
"""
|
"""
|
||||||
The last sample of the preprocessor. This is used for low frequency processing
|
The last sample of the preprocessor. This is used for low frequency processing
|
||||||
"""
|
"""
|
||||||
|
match config.preprocessing.denoising:
|
||||||
|
case "none":
|
||||||
return self._last_sample
|
return self._last_sample
|
||||||
|
case "median":
|
||||||
|
# Return the median of the last samples
|
||||||
|
median_abs = np.median(np.abs(self.circular_buffer), axis=0)
|
||||||
|
median_angle = np.median(np.angle(self.circular_buffer), axis=0)
|
||||||
|
ans = median_abs * np.exp(1j * median_angle)
|
||||||
|
return ans
|
||||||
|
case "mean":
|
||||||
|
# Return the mean of the last samples
|
||||||
|
return np.mean(self.circular_buffer, axis=0)
|
||||||
|
case _:
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid denoising method: {config.preprocessing.denoising}"
|
||||||
|
)
|
||||||
|
|
||||||
def remove_sto(self, csi: CSIMatrix) -> CSIMatrix:
|
def remove_sto(self, csi: CSIMatrix) -> CSIMatrix:
|
||||||
"""
|
"""
|
||||||
@ -134,6 +164,10 @@ class Preprocessor:
|
|||||||
# h_hat -= self.long_term_avg
|
# h_hat -= self.long_term_avg
|
||||||
|
|
||||||
self._last_sample = h_hat
|
self._last_sample = h_hat
|
||||||
|
|
||||||
|
if config.preprocessing.denoising != "none":
|
||||||
|
self.circular_buffer[self.sample_index] = h_hat
|
||||||
|
self.sample_index = (self.sample_index + 1) % self.denoising_samples
|
||||||
return h_hat
|
return h_hat
|
||||||
|
|
||||||
# Apply bandpass filter to remove low and high frequency noise
|
# Apply bandpass filter to remove low and high frequency noise
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user