传统目标跟踪——卡尔曼滤波Kalman(结合MeanShift+Kalman)

目录

一、Kalman

二、流程

三、代码

3.1 meanshift+kalman实现


kalman被用来描述目标的运动模型,它不对目标的特征建模,而是对目标的运动模型进行建模,常用于估计目标在下一帧的位置。

一、Kalman

        在上面的跟踪中,meanshiftcamshift链接。我们使用的都是Meanshift或者是基于Meanshift的Camshift来进行的跟踪,这里我们还可以对其进行改良:引入卡尔曼滤波的概念。

        卡尔曼滤波的概念较为复杂,这里我们可以理解为:从一个含有噪音的输入中,得出一个具有统计意义上较为良好的估计值。  

        我们举个简单的例子,比如我现在有一个物体,正在以1m/s的速度(过去测量得到的值)离我远去,当前它离我1m远,因为我们知道他正在以1m/s的速度远离我,所以下一秒我就能估计出它离我2m远,这个是显然的。但是如果这个物体撞到了什么东西后,速度改变了,我们就会根据它实际位置上的值(含有噪音的模糊输入)来矫正我们的猜测。 卡尔曼滤波一般我们设置为4个参数,其中两个是可以直接得到的。举个例子,我们使用函数来创建一个卡尔曼滤波器:

klm=cv2.KalmanFilter(4,2)

        这里的4表示的是有四个参数分别是(x,y,dx,dy),前两个是我们输入进去的参数,物体跟踪里面我们假定为我们跟踪物体的中心的坐标,dx和dy表示的是物体移动的速度,为观测量,不能直接得到,所以其实我们能直接输入进去的参数就只有坐标,x和y两个值,所以初始化的时候4后面跟一个2,所以就是(4,2) 然后我们需要设置卡尔曼滤波器的几个矩阵:  

klm.measurementMatrix = np.array([[1,0,0,0],[0,1,0,0]],np.float32)
klm.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],np.float32)
klm.processNoiseCov = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],np.float32)

        参数:

  • measurementMatrix,测量矩阵,这里表示的是我们能直接测量得到的参数(x,y,dx,dy)中的前两位,所以只有[1,0,0,0],[0,1,0,0],来标记第一位和第二位。
  • transitionMatrix,状态转移矩阵,为[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1],表示的是(x+dx,y+dy),这里的含义其实就是算上速度后下一个时刻的估计。
  • processNoiseCov,这个是在为预测进行修正卡尔曼滤波里面几个方程中的参数,依次参考的次序为x,y,dx,dy。

二、流程

三、代码

3.1 meanshift+kalman实现

        现在我们对上文优化的基础上,再加入卡尔曼滤波,我们把矩形框的中间位置作为输入,加载到卡尔曼滤波器中,预测出现在物体的位置后,以预测位置为圆心画一个圆,示例代码如下所示:

import cv2
import numpy as np


def center(points):
    x = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4
    y = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4
    return np.array([np.float32(x), np.float32(y)], np.float32)


cap = cv2.VideoCapture('E:\Python-Code/videodataset/enn.mp4')
ret, frame = cap.read()
# 我这里画面太大了所以缩小点
# frame = cv2.resize(frame, None, None, fx=1 / 2, fy=1 / 2, interpolation=cv2.INTER_CUBIC)
# 跟踪框
track_window = cv2.selectROI('img', frame)

# 获得绿色的直方图
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, np.array((35, 43, 46)), np.array((77, 255, 255)))
hist = cv2.calcHist([hsv], [0], mask, [181], [0, 180])
cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)

term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

# 设置卡尔曼滤波器
klm = cv2.KalmanFilter(4, 2)
klm.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32)
klm.transitionMatrix = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32)
klm.processNoiseCov = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32)

while 1:
    ret, frame = cap.read()
    # frame = cv2.resize(frame, None, None, fx=1 / 2, fy=1 / 2, interpolation=cv2.INTER_CUBIC)
    if ret == True:
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        dst = cv2.calcBackProject([hsv], [0], hist, [0, 180], 1)
        ret, track_window = cv2.meanShift(dst, track_window, term_crit)
        x, y, w, h = track_window

        # 获得中间坐标
        cent = center([[x, y], [x + w, y], [x, y + h], [x + w, y + h]])
        # 修正参数
        klm.correct(cent)
        # 预测
        c = klm.predict()
        # 画出预测位置
        cv2.circle(frame, (int(c[0]), int(c[1])), 30, (255, 255, 0), -1)
        # 画出矩形框
        img = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        (x, y) = img.shape[:2]
        cv2.imshow('img', img)
        if cv2.waitKey(1) == ord('q'):
            break
    else:
        break
cap.release()
cv2.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/weixin_45823221/article/details/128484856
今日推荐