Kalman FIlter в видео
Как я могу использовать фильтр Калмана, чтобы отслеживать движения человека в видео в режиме реального времени? Я новичок в Калман, и я экспериментировал с ним. Мне удалось запустить Калмана и предсказать путь мяча в видео.
Вот код для вычитания фона:
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()
Вот код для фильтра Калмана с постоянной скоростью:
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 ответ
Код ниже показывает пример того, как использовать filter_update
метод, чтобы взять один кадр из видео за один раз, и обновить оценку состояния.
Это более или менее основано на коде, которым вы поделились, за исключением того, что я использовал kf.smooth
способ оценки свойств фильтра Калмана на основе первой половины кадров, а затем обновление оценки состояния (положения) с использованием фильтра для последующих кадров. pykalman
smooth
метод будет работать на серии измерений и попытаться оценить ковариацию и т. д.
Я также изменил график, чтобы вы могли видеть обновленную оценку состояния во время воспроизведения видео.
Вы увидите, что фильтр Калмана с постоянной скоростью выполняет разумную работу, оценивая, где находится шарик под коробкой (и когда он появится снова).
Код:
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')