Kalman FIlter в видео

Как я могу использовать фильтр Калмана для отслеживания движений человека в видео в режиме реального времени? Я новичок в kalman, и я экспериментировал с ним. Я смог запустить калман и предсказать путь мяча в видео.

Вот код для вычитания фона:

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

Теперь проблема в том, что я сохраняю траекторию в файле, а затем использую этот файл в качестве входных данных для калмана. Как я могу расширить это, чтобы сделать его в режиме реального времени? а также Как отследить одного человека в группе, в которой могут находиться и двигаться несколько человек?

Версия Python: 2.7

Версия OpenCV: 2.4.13


person sks    schedule 22.03.2017    source источник
comment
Посмотрите видео Студента Дэйва, там есть хорошие пояснения с кодом в Matlab: youtube.com/watch?v= FkCT_LV9Syk   -  person Andrey Smorodov    schedule 22.03.2017
comment
@sks вы захотите проверить метод filter_update, см. здесь. Это позволяет предоставить одно новое измерение и возвращает обновленную оценку состояния.   -  person kabdulla    schedule 03.05.2017


Ответы (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')
person kabdulla    schedule 05.05.2017