Gaze-LIPE / src /utils /filters.py
thanhhuyvan's picture
Initial release of LIPE V2 GOLD
a10ba7f
Raw
History Blame Contribute Delete
2.4 kB
import numpy as np
import time
class LowPassFilter:
def __init__(self, alpha):
self.__set_alpha(alpha)
self.__y = None
def __set_alpha(self, alpha):
if not (0.0 <= alpha <= 1.0):
raise ValueError("alpha must be between 0.0 and 1.0")
self.__alpha = alpha
def __call__(self, value, timestamp=None, alpha=None):
if alpha is not None:
self.__set_alpha(alpha)
if self.__y is None:
self.__y = value
else:
self.__y = self.__alpha * value + (1.0 - self.__alpha) * self.__y
return self.__y
def last_value(self):
return self.__y
class OneEuroFilter:
"""
Adaptive low-pass filter for jitter suppression.
Based on: http://www.lifl.fr/~casiez/1euro/
"""
def __init__(self, freq, min_cutoff=1.0, beta=0.007, d_cutoff=1.0):
self.__freq = freq
self.__min_cutoff = min_cutoff
self.__beta = beta
self.__d_cutoff = d_cutoff
self.__x_filt = LowPassFilter(self.__alpha(min_cutoff))
self.__dx_filt = LowPassFilter(self.__alpha(d_cutoff))
self.__last_time = None
def __alpha(self, cutoff):
tau = 1.0 / (2 * np.pi * cutoff)
te = 1.0 / self.__freq
return 1.0 / (1.0 + tau / te)
def __call__(self, x, timestamp=None):
# Update frequency if timestamp is provided
if timestamp is not None and self.__last_time is not None:
self.__freq = 1.0 / (timestamp - self.__last_time)
self.__last_time = timestamp
# Estimate the derivative
prev_x = self.__x_filt.last_value()
dx = 0.0 if prev_x is None else (x - prev_x) * self.__freq
edx = self.__dx_filt(dx, alpha=self.__alpha(self.__d_cutoff))
# Compute the optimal cutoff frequency
cutoff = self.__min_cutoff + self.__beta * abs(edx)
# Filter the value
return self.__x_filt(x, alpha=self.__alpha(cutoff))
if __name__ == "__main__":
# Quick test
filter = OneEuroFilter(freq=30, min_cutoff=1.0, beta=0.01)
data = [10.0, 10.1, 10.5, 13.0, 15.0, 15.1]
timestamps = [0.0, 0.033, 0.066, 0.1, 0.133, 0.166]
print("Testing OneEuroFilter:")
for val, ts in zip(data, timestamps):
filtered = filter(val, timestamp=ts)
print(f"Input: {val:.2f}, Filtered: {filtered:.2f}")