Kalman FIlter in a video
如何使用卡尔曼滤波器实时跟踪视频中人物的运动?我是卡尔曼(Kalman)的新手,正在尝试中。我已经能够运行kalman并预测视频中球的路径。
以下是背景扣除的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import cv2 import numpy as np import matplotlib.pyplot as plt file="singleball.mov" capture = cv2.VideoCapture(file) print"\\t Width:",capture.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH) print"\\t Height:",capture.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT) print"\\t FourCC:",capture.get(cv2.cv.CV_CAP_PROP_FOURCC) print"\\t Framerate:",capture.get(cv2.cv.CV_CAP_PROP_FPS) numframes=capture.get(7) print"\\t Number of Frames:",numframes count=0 history = 10 nGauss = 3 bgThresh = 0.6 noise = 20 bgs = cv2.BackgroundSubtractorMOG(history,nGauss,bgThresh,noise) plt.figure() plt.hold(True) plt.axis([0,480,360,0]) measuredTrack=np.zeros((numframes,2))-1 while count<numframes: count+=1 img2 = capture.read()[1] cv2.imshow("Video",img2) foremat=bgs.apply(img2) cv2.waitKey(100) foremat=bgs.apply(img2) ret,thresh = cv2.threshold(foremat,127,255,0) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) if len(contours) > 0: m= np.mean(contours[0],axis=0) measuredTrack[count-1,:]=m[0] plt.plot(m[0,0],m[0,1],'ob') cv2.imshow('Foreground',foremat) cv2.waitKey(80) capture.release() print measuredTrack np.save("ballTrajectory", measuredTrack) plt.show() |
这是恒速卡尔曼滤波器的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import numpy as np from pykalman import KalmanFilter from matplotlib import pyplot as plt Measured=np.load("ballTrajectory.npy") while True: if Measured[0,0]==-1.: Measured=np.delete(Measured,0,0) else: break numMeas=Measured.shape[0] MarkedMeasure=np.ma.masked_less(Measured,0) Transition_Matrix=[[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]] Observation_Matrix=[[1,0,0,0],[0,1,0,0]] xinit=MarkedMeasure[0,0] yinit=MarkedMeasure[0,1] vxinit=MarkedMeasure[1,0]-MarkedMeasure[0,0] vyinit=MarkedMeasure[1,1]-MarkedMeasure[0,1] initstate=[xinit,yinit,vxinit,vyinit] initcovariance=1.0e-3*np.eye(4) transistionCov=1.0e-4*np.eye(4) observationCov=1.0e-1*np.eye(2) kf=KalmanFilter(transition_matrices=Transition_Matrix, observation_matrices =Observation_Matrix, initial_state_mean=initstate, initial_state_covariance=initcovariance, transition_covariance=transistionCov, observation_covariance=observationCov) (filtered_state_means, filtered_state_covariances) = kf.filter(MarkedMeasure) plt.plot(MarkedMeasure[:,0],MarkedMeasure[:,1],'xr',label='measured') plt.axis([0,520,360,0]) plt.hold(True) plt.plot(filtered_state_means[:,0],filtered_state_means[:,1],'ob',label='kalman output') plt.legend(loc=2) plt.title("Constant Velocity Kalman Filter") plt.show() |
我使用的视频链接:https://www.hdm-stuttgart.de/~maucher/Python/ComputerVision/html/files/singleball.mov
现在,问题出在这里,我将轨迹存储在一个文件中,然后将那个文件用作kalman的输入。我如何扩展它以使其实时?以及如何在可能有多个人出现并移动的组中跟踪单个人?
Python版本:2.7
OpenCV版本:2.4.13
下面的代码显示了如何使用
或多或少地基于您共享的代码,除了我已使用
我还修改了绘图,以便您可以在播放视频时看到更新的状态估计。
您将看到等速卡尔曼滤波器在估算球在盒子下方的位置(以及何时再次出现)方面做得很合理。
图(在视频末尾):
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | import cv2 import numpy as np import matplotlib.pyplot as plt from pykalman import KalmanFilter # Main settings: file="singleball.mov" filter_train_ratio = 0.5 capture = cv2.VideoCapture(file) numframes=int(capture.get(7)) numframes_train = int(filter_train_ratio*numframes) print"\\t Total No. Frames:", numframes print"\\t No. Frames Train:", numframes_train # Background filter settings: history = 10 nGauss = 3 bgThresh = 0.6 noise = 20 bgs = cv2.BackgroundSubtractorMOG(history,nGauss,bgThresh,noise) f = plt.figure() plt.ion() plt.axis([0,480,360,0]) measuredTrack = np.zeros((numframes_train,2))-1 measurementMissingIdx = [False]*numframes_train # Get measured trace to train a Kalman Filter: count=0 legendPlotted = False while count<numframes_train: count+=1 img2 = capture.read()[1] cv2.imshow("Video",img2) foremat=bgs.apply(img2) cv2.waitKey(100) foremat=bgs.apply(img2) ret,thresh = cv2.threshold(foremat,127,255,0) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) if len(contours) > 0: m= np.mean(contours[0],axis=0) measuredTrack[count-1,:]=m[0] if not legendPlotted: plt.plot(m[0,0],m[0,1],'ob', label='measurement') plt.legend(loc=2) legendPlotted = True else: plt.plot(m[0,0],m[0,1],'ob') plt.pause(0.05) else: measurementMissingIdx[count-1] = True cv2.imshow('Foreground',foremat) cv2.waitKey(80) # Train the Kalman filter: measurements = np.ma.asarray(measuredTrack) measurements[measurementMissingIdx] = np.ma.masked # Kalman filter settings: Transition_Matrix=[[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]] Observation_Matrix=[[1,0,0,0],[0,1,0,0]] kf=KalmanFilter(transition_matrices=Transition_Matrix, observation_matrices =Observation_Matrix) (smoothed_state_means, smoothed_state_covariances) = kf.smooth(measurements) plt.plot(smoothed_state_means[:,0],smoothed_state_means[:,1],'xr',label='kalman output') legend = plt.legend(loc=2) plt.title("Constant Velocity Kalman Filter") # Apply (pre-trained) filter one interval at a time, # with plotting in real time. x_now = smoothed_state_means[-1, :] P_now = smoothed_state_covariances[-1, :] legendPlotted = False while count<numframes: newMeasurement = np.ma.asarray(-1) count+=1 img2 = capture.read()[1] cv2.imshow("Video",img2) foremat=bgs.apply(img2) cv2.waitKey(100) foremat=bgs.apply(img2) ret,thresh = cv2.threshold(foremat,127,255,0) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) if len(contours) > 0: m= np.mean(contours[0],axis=0) newMeasurement = np.ma.asarray(m[0]) else: newMeasurement = np.ma.masked cv2.imshow('Foreground',foremat) cv2.waitKey(80) (x_now, P_now) = kf.filter_update(filtered_state_mean = x_now, filtered_state_covariance = P_now, observation = newMeasurement) if not legendPlotted: plt.plot(x_now[0],x_now[1],'xg', label='kalman update') legendPlotted = True plt.legend(loc=2) else: plt.plot(x_now[0],x_now[1],'xg') plt.pause(0.05) f.savefig("so_42941634.pdf", bbox_inches='tight') |