2017-03-22 5 views
1

Comment puis-je utiliser le filtre de Kalman pour suivre les mouvements d'une personne dans une vidéo en temps réel? Je suis nouveau à Kalman et je l'expérimentais. J'ai été capable de lancer kalman et prédire le chemin d'une balle dans une vidéo.Kalman FIlter dans une vidéo

est ici le code de soustractions de fond:

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() 

Voici le code pour Constant filtre de Kalman de vitesse:

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() 

Lien de la vidéo que je l'ai utilisé: https://www.hdm-stuttgart.de/~maucher/Python/ComputerVision/html/files/singleball.mov

Maintenant, le problème est ici je stocke la trajectoire dans un fichier et puis j'utilise ce fichier comme une entrée pour kalman. Comment puis-je étendre cela pour le rendre en temps réel? et aussi Comment suivre une seule personne dans un groupe où plusieurs personnes peuvent être présentes et en mouvement?

Python version: 2.7

version OpenCV: 2.4.13

+0

Vérifiez étudiants Vidéos de Dave, il y a de bonnes explications avec le code Matlab: https://www.youtube.com/watch? v = FkCT_LV9Syk –

+0

@sks vous voudrez vérifier la méthode 'filter_update', voir [ici] (https://pykalman.github.io/#pykalman.KalmanFilter.filter_update). Cela vous permet de fournir une nouvelle mesure unique et renvoie l'estimation d'état mise à jour. – kabdulla

Répondre

1

Le code ci-dessous montre un exemple de la façon d'utiliser la méthode filter_update pour prendre une seule image de la vidéo à un moment , et mettre à jour l'estimation de l'état. C'est plus ou moins basé sur le code que vous avez partagé, sauf que j'ai utilisé la méthode kf.smooth pour estimer les propriétés du filtre kalman en fonction de la première moitié des images, puis mettre à jour l'estimation de l'état (position) utiliser le filtre pour les trames suivantes. La méthode pykalmansmooth fonctionnera sur un lot de mesures et d'essayer d'estimer la covariance etc.

J'ai aussi modifié le tracé afin que vous puissiez voir l'estimation de l'état mis à jour comme les jeux vidéo.

Vous verrez que le filtre de Kalman à vélocité constante fait un travail raisonnable d'estimation de l'endroit où la balle se trouve sous la boîte (et quand elle apparaîtra à nouveau).

Figure (à la fin de la vidéo): enter image description here

code:

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')