import cv2 import numpy as np from scipy.signal import savgol_filter def kalman_filter(inputs: np.array, process_noise: float = 0.03, measure_noise: float = 0.01, ): """ OpenCV - Kalman Filter https://blog.csdn.net/angelfish91/article/details/61768575 https://blog.csdn.net/qq_23981335/article/details/82968422 """ assert inputs.ndim == 2, "inputs should be 2-dim np.array" ''' 它有3个输入参数, dynam_params:状态空间的维数,这里为2; measure_param:测量值的维数,这里也为2; control_params:控制向量的维数,默认为0。由于这里该模型中并没有控制变量,因此也为0。 ''' kalman = cv2.KalmanFilter(2,2) kalman.measurementMatrix = np.array([[1,0],[0,1]],np.float32) kalman.transitionMatrix = np.array([[1,0],[0,1]], np.float32) kalman.processNoiseCov = np.array([[1,0],[0,1]], np.float32) * process_noise kalman.measurementNoiseCov = np.array([[1,0],[0,1]], np.float32) * measure_noise ''' kalman.measurementNoiseCov为测量系统的协方差矩阵,方差越小,预测结果越接近测量值, kalman.processNoiseCov为模型系统的噪声,噪声越大,预测结果越不稳定,越容易接近模型系统预测值,且单步变化越大, 相反,若噪声小,则预测结果与上个计算结果相差不大。 ''' kalman.statePre = np.array([[inputs[0][0]], [inputs[0][1]]]) ''' Kalman Filtering ''' outputs = np.zeros_like(inputs) for i in range(len(inputs)): mes = np.reshape(inputs[i,:],(2,1)) x = kalman.correct(mes) y = kalman.predict() outputs[i] = np.squeeze(y) # print (kalman.statePost[0],kalman.statePost[1]) # print (kalman.statePre[0],kalman.statePre[1]) # print ('measurement:\t',mes[0],mes[1]) # print ('correct:\t',x[0],x[1]) # print ('predict:\t',y[0],y[1]) # print ('='*30) return outputs def kalman_filter_landmark(landmarks: np.array, process_noise: float = 0.03, measure_noise: float = 0.01, ): """ Kalman Filter for Landmarks :param process_noise: large means unstable and close to model predictions :param measure_noise: small means close to measurement """ print('[Using Kalman Filter for Landmark Smoothing, process_noise=%f, measure_noise=%f]' % (process_noise, measure_noise)) ''' landmarks: (#frames, key, xy) ''' assert landmarks.ndim == 3, 'landmarks should be 3-dim np.array' assert landmarks.dtype == 'float32', 'landmarks dtype should be float32' for s1 in range(landmarks.shape[1]): landmarks[:, s1] = kalman_filter(landmarks[:, s1], process_noise, measure_noise) return landmarks def savgol_filter_landmark(landmarks: np.array, window_length: int = 25, poly_order: int = 2, ): """ Savgol Filter for Landmarks https://blog.csdn.net/kaever/article/details/105520941 """ print('[Using Savgol Filter for Landmark Smoothing, window_length=%d, poly_order=%d]' % (window_length, poly_order)) ''' landmarks: (#frames, key, xy) ''' assert landmarks.ndim == 3, 'landmarks should be 3-dim np.array' assert landmarks.dtype == 'float32', 'landmarks dtype should be float32' assert window_length % 2 == 1, 'window_length should be odd' for s1 in range(landmarks.shape[1]): for s2 in range(landmarks.shape[2]): landmarks[:, s1, s2] = savgol_filter(landmarks[:, s1, s2], window_length, poly_order) return landmarks if __name__ == '__main__': pos = np.array([ [10, 50], [12, 49], [11, 52], [13, 52.2], [12.9, 50]], np.float32) print(pos) pos_filtered = kalman_filter(pos) print(pos) print(pos_filtered)