Kalman filter always predicting origin

╄→гoц情女王★ 提交于 2020-01-05 05:28:25

问题


I am learning kalman filters for the purpose of trajectory prediction. Right now, I am able to track the ball. For my first practical attempt with prediction and kalman filter, I used an example of drawing lines as given here:

Is there any example of cv2.KalmanFilter implementation?

Here is the complete code:

import cv2
import numpy as np
import math
cap = cv2.VideoCapture('videoplayback (1).mp4')
loHue = 0
loSaturation = 50
loValue = 50
high_hue = 0
high_saturation = 255
high_value = 255
flag_for_center = 1
def low_hue(x):
    global loHue
    loHue = x 

#def low_saturation(x):
    #global loSaturation
    #loSaturation = x

#def low_value(x):
    #global loValue
    #loValue = x

def upper_hue (x):
    global high_hue
    high_hue = x

#def upper_saturation(x):
    #global high_saturation
    #high_saturation= x

#def upper_value(x):
    #global high_value
    #high_value = x

cv2.namedWindow('Trackbars', flags=cv2.WINDOW_OPENGL)
cv2.resizeWindow('Trackbars', 500, 30)
cv2.moveWindow('Trackbars', 500, 600)
cv2.createTrackbar('loHue', 'Trackbars', 0, 180, low_hue)
#cv2.createTrackbar('loSaturation', 'Trackbars', 0, 255, low_saturation)
#cv2.createTrackbar('lowValue', 'Trackbars', 0, 255, low_value)
cv2.createTrackbar('upperHue', 'Trackbars', 0, 180, upper_hue)
#cv2.createTrackbar('upperSat', 'Trackbars', 0, 255, upper_saturation)
#cv2.createTrackbar('upperValue', 'Trackbars', 0, 255, upper_value)
cv2.setTrackbarPos('loHue', 'Trackbars', 5)
cv2.setTrackbarPos('upperHue', 'Trackbars', 30)

frame_count = 0
measure = []
predicted = []

while(True):




_, image = cap.read()
frame_count = frame_count + 1
image = cv2.GaussianBlur(image, (3, 3), 2)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_limit = np.array([loHue,loSaturation,loValue])
upper_limit = np.array([high_hue,high_saturation,high_value])
mask = cv2.inRange(hsv, lower_limit, upper_limit)
res = cv2.bitwise_and(image, image, mask = mask)
#b,g,r = cv2.split(res)
#b = cv2.adaptiveThreshold(b,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
#   cv2.THRESH_BINARY,11,20)
#g = cv2.adaptiveThreshold(g,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
#   cv2.THRESH_BINARY, 11,20)
#r = cv2.adaptiveThreshold(r,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
#   cv2.THRESH_BINARY,11,20)    
#res = cv2.merge((b,g,r))           
erode_element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dilate_element = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
erosion = cv2.erode(mask, erode_element, iterations = 1)
erosion = cv2.erode(erosion, erode_element, iterations = 1)
dilation = cv2.dilate(erosion, dilate_element, iterations = 1)
dilation = cv2.dilate(dilation, dilate_element, iterations = 1)
copy_dilation = dilation.copy()

_, contours, hierarchy = cv2.findContours(copy_dilation, cv2.RETR_CCOMP, 
 cv2.CHAIN_APPROX_SIMPLE)
center = None

if len(contours) > 0:
    c = max(contours, key = cv2.contourArea)
    ((x, y), radius) = cv2.minEnclosingCircle(c)
    M = cv2.moments(c)
    center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
    x,y = center

    measure = np.array([[np.float32(x)],[np.float32(y)]])
    #print(measure)
    #if (radius>10):
    #   cv2.circle(image, (int(x), int(y)), int(radius), (0, 255, 255), -2)
    #   cv2.circle(image, center, 3, (0,0,255),-1)
kalman = cv2.KalmanFilter(4,2)

kalman.transitionMatrix = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32)
kalman.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32)
kalman.processNoiseCov = np.array([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]],np.float32) * 0.03

#while(True):
kalman.correct(measure)
update_predicted_state = kalman.predict()
predicted.append((int(update_predicted_state[0]), int(update_predicted_state[1])))
for i in range(len(predicted)-1):
    cv2.imshow('tracking', image)
    cv2.moveWindow('tracking', 150, 150)
    cv2.imshow('mask', mask)
    cv2.moveWindow('mask', 700, 150)
    cv2.circle(image, (predicted[i][0], predicted[i + 1][1]), int(radius), (0, 255, 255), -2)
k = cv2.waitKey(20) & 0xFF
if k ==27:
    break
cap.release()
cv2.destroyAllWindows()

The issue is that the predicted values are all zero. As a result, I am getting a quarter circle at the top left corner. Any explanation ? BTW, the video on which I am running this thing is here: https://www.youtube.com/watch?v=CcFVOzQ1Oqc

The tracking part is working good and I am able to track the ball. However the problem starts with this line:

kalman.correct(measure)

When I tried to print it, it was all zero

[[0.]
[0.]
[0.]
[0.]]

Is it because I have not considered control matrix here ? Or is it just because of the odd bouncing of the ball ?

As you might have guessed it, the frame rates are awfully low.

Thank you.


回答1:


There is a better explanation here: KalmanFilter always predict 0,0 in first time

The Kalman filter implementation of opencv doesn't let you set an initial state. This is not intuitive and the lack of documentation makes things even worse.

The way to circumvent this problem is to override the kalman.correct and kalman.predict methods. You set an initial value of the variable you want to work with and every time you call correct, you first subtract the initial value. When you call predict, you have to add the initial value.

I have an implementation example here where the Kalman filter is used in an visual tracking problem (tracking car chased by police): https://github.com/fredguth/unb-cv-3183/blob/master/p6/r4.py




回答2:


I tried a loop to get rid of the offset. It may affect the estimator though. Probably, not a good way to handle the initial offset.

Mat_<float> measurement(2, 1);

KF.statePre.at<float> (0) = curMeasurement.x;
KF.statePre.at<float> (1) = curMeasurement.y;
KF.statePre.at<float> (2) = 0;
KF.statePre.at<float> (3) = 0;

measurement(0) = curMeasurement.x;
measurement(1) = curMeasurement.y;

for (int i = 0; i < 100; i++) {
  KF.predict();
  KF.correct(measurement);
}


来源:https://stackoverflow.com/questions/50863397/kalman-filter-always-predicting-origin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!