Spaces:
Running
Running
| 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) |