第八章 目标跟踪

简介: 第八章 目标跟踪

第八章 目标跟踪

8.1 检测移动的目标

基本的运动检测

计算帧之间的差异,或考虑“背景”帧与其他帧之间的差异。

例:

import cv2
import numpy as np
camera = cv2.VideoCapture(0)

es =  cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,4))
kernel = np.ones((5,5),np.uint8)
#通过摄像头读入帧,将第一帧设置为背景
background = None
while(True):
    rat,frame = camera.read()
    if background is None:
        background = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        background = cv2.GaussianBlur(background,(21,21),0)
        continue
    #对帧进行简单处理:转化灰阶、模糊处理(减少噪声影响)
    gray_frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    gray_frame = cv2.GaussianBlur(gray_frame,(21,21),0)
#差分图difference map,
    diff = cv2.absdiff(background,gray_frame)
    diff = cv2.threshold(diff,25,255,cv2.THRESH_BINARY)[1]
    diff = cv2.dilate(diff,es,iterations=2)
#显示矩形
    image,cnts,hierarchy = cv2.findContours(diff.copy(),cv2.RETR_EXTERNAL,
                                            cv2.CHAIN_APPROX_SIMPLE)
    for c in cnts:
        if cv2.contourArea(c)<1500:
            continue
        (x,y,w,h) = cv2.boundingRect(c)
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)

    cv2.imshow("contours",frame)
    cv2.imshow("dif",diff)
    if cv2.waitKey(82) & 0xff == ord("q"):
        break

cv2.destroyAllWindows()

8.2 背景分割器:KNN、MOG2和GMG

OpenCV提供了一个BackgroundSubtractor的类,在分割前景和背景时很方便。BackgroundSubtractor类 可以计算阴影。

例子BackgroundSubtractor

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
mog = cv2.createBackgroundSubtractorMOG2()
while(1):
    rat,frame = cap.read()
    fgmask = mog.apply(frame)

    cv2.imshow('frame',fgmask)
    if cv2.waitKey(30) & 0xff == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

例:使用BackgroundSubtractorKNN来实现运动检测

import  cv2

import numpy as np

bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)

camera = cv2.VideoCapture('traffic.flv')
# traffic.flv一段公路上的交通情况

while True:

    rat,frame = camera.read()

    fgmask = bs.apply(frame)

    th = cv2.threshold(fgmask.copy(),244,255,cv2.THRESH_BINARY)[1]

    dilated = cv2.dilate(th,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),

    iterations = 2)

    image,contours,hier = cv2.findContours(dilated,cv2.RETR_EXTERNAL,

                                           cv2.CHAIN_APPROX_SIMPLE)

    for c in contours:

        if cv2.contourArea(c)>1600:

            (x,y,w,h) = cv2.boundingRect(c)

            cv2.rectangle(frame,(x,y),(x+w,y+h),(255,255,0),2)

    cv2.imshow("mog",fgmask)

    cv2.imshow("thresh",th)

    cv2.imshow("detection",frame)

    if cv2.waitKey(30) & 0xff ==27:

        break

camera.release()

cv2.destroyAllWindows()

8.2.1 均值漂移和CAMShift

均值漂移Meanshift是一种目标跟踪算法,该算法寻找概率函数离散样本的最大密度,并且重新计算下一帧的最大密度,该算法给出了目标的移动方向。

均值漂移在追踪视频中感兴趣的区域时非常有用。

例:标记并追踪感兴趣的区域:

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
ret,frame = cap.read()
r,h,c,w = 10,200,10,200
track_window = (c,r,w,h)

roi = frame[r:r+h,c:c+w]
hsv_roi = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi,np.array((100.,30.,32.)),
                   np.array((180.,120.,255.)))
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)

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

while True:
    ret,frame = cap.read()
    if ret == True:
        hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
        dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)

        ret,track_window = cv2.meanShift(dst,track_window,term_crit)

        x,y,w,h = track_window
        img2 = cv2.rectangle(frame,(x,y),(x+w,y+h),255,2)
        cv2.imshow('img2',img2)

        if cv2.waitKey(60) & 0xff == ord("q"):
            break
    else:
        break
cv2.destroyAllWindows()
cap.release()
 

如果有颜色范围内的物体进入窗口,就会追踪物体。


8.2.2 彩色直方图

calcHist 函数用来计算图像的彩色直方图。彩色直方图是图像的颜色分布。x轴是色彩值,y轴是像素数量。

calcBackProject 函数 在均值漂移算法中非常重要。称为直方图方向投影,它得到直方图并将其投影到一副图像上,其结果是每个像素属于生成原始直方图的原图像的概率。

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
ret,frame = cap.read()
#标记感兴趣的区域
r,h,c,w = 10,200,10,200
track_window = (c,r,w,h)
#提取roi并将其转换为HSV空间
roi = frame[r:r+h,c:c+w]
hsv_roi = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi,np.array((100.,30.,32.)),
                   np.array((180.,120.,255.)))

#roi的直方图
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
#均值漂移停止条件 :迭代10次或 中心移动1个像素
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,10,1)

while True:
    ret,frame = cap.read()
    if ret == True:
        hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
        #反向投影
        dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)

        ret,track_window = cv2.meanShift(dst,track_window,term_crit)

        x,y,w,h = track_window
        img2 = cv2.rectangle(frame,(x,y),(x+w,y+h),255,2)
        cv2.imshow('img2',img2)

        if cv2.waitKey(60) & 0xff == ord("q"):
            break
    else:
        break
cv2.destroyAllWindows()
cap.release()
 

8.3CAMShift

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
ret,frame = cap.read()
#标记感兴趣的区域
r,h,c,w = 10,200,10,200
track_window = (c,r,w,h)
#提取roi并将其转换为HSV空间
roi = frame[r:r+h,c:c+w]
hsv_roi = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi,np.array((100.,30.,32.)),
                   np.array((180.,120.,255.)))

#roi的直方图
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
#均值漂移停止条件 :迭代10次或 中心移动1个像素
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,10,1)

while True:
    ret,frame = cap.read()
    if ret == True:
        hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
        #反向投影
        dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)

        ret,track_window = cv2.CamShift(dst,track_window,term_crit)
        pts = cv2.boxPoints(ret)
        pts = np.int0(pts)
        img2 = cv2.polylines(frame,[pts],True,255,2)
        cv2.imshow('img2',img2)

        if cv2.waitKey(60) & 0xff == ord("q"):
            break
    else:
        break
cv2.destroyAllWindows()
cap.release()
 

8.4 卡尔曼滤波器

卡尔曼滤波器对含有噪声的输入数据流进行递归操作,产生底层系统状态在统计意义上的最优估计。

8.4.1 预测和更新

可将卡尔曼滤波算法分为两个阶段:

预测:使用当前点计算的协方差来估计目标的新位置

更新:记录目标位置,为下一次循环计算修正协方差

例:卡尔曼滤波器预测鼠标轨迹

import cv2, numpy as np



measurements = []

predictions = []

frame = np.zeros((800, 800, 3), np.uint8)

last_measurement = current_measurement = np.array((2,1), np.float32) 

last_prediction = current_prediction = np.zeros((2,1), np.float32)



def mousemove(event, x, y, s, p):

    global frame, current_measurement, measurements, last_measurement, current_prediction, last_prediction

    last_prediction = current_prediction

    last_measurement = current_measurement

    current_measurement = np.array([[np.float32(x)],[np.float32(y)]])

    kalman.correct(current_measurement)

    current_prediction = kalman.predict()

    lmx, lmy = last_measurement[0], last_measurement[1]

    cmx, cmy = current_measurement[0], current_measurement[1]

    lpx, lpy = last_prediction[0], last_prediction[1]

    cpx, cpy = current_prediction[0], current_prediction[1]

    cv2.line(frame, (lmx, lmy), (cmx, cmy), (0,100,0))

    cv2.line(frame, (lpx, lpy), (cpx, cpy), (0,0,200))





cv2.namedWindow("kalman_tracker")

cv2.setMouseCallback("kalman_tracker", mousemove);



kalman = cv2.KalmanFilter(4,2,1)

kalman.measurementMatrix = np.array([[1,0,0,0],[0,1,0,0]],np.float32)

kalman.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],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:

    cv2.imshow("kalman_tracker", frame)

    if (cv2.waitKey(30) & 0xFF) == 27:

        break

    if (cv2.waitKey(30) & 0xFF) == ord('q'):

        cv2.imwrite('kalman.jpg', frame)

        break



cv2.destroyAllWindows()

8.3 CAMShift

 

相关文章
|
7月前
|
算法 计算机视觉
yolov5 deepsort-船舶目标检测+目标跟踪+单目测距+速度测量(代码+教程)
yolov5 deepsort-船舶目标检测+目标跟踪+单目测距+速度测量(代码+教程)
|
7月前
|
算法 计算机视觉
【目标跟踪】一图看懂DeepSORT大流程
【目标跟踪】一图看懂DeepSORT大流程
349 1
|
机器学习/深度学习 传感器 编解码
2023最新 | 单目深度估计网络结构的通用性研究
单目深度估计已经被广泛研究,最近已经报道了许多在性能上显著改进的方法。然而,大多数先前的工作都是在一些基准数据集(如KITTI数据集)上进行评估的,并且没有一项工作对单目深度估计的泛化性能进行深入分析。本文深入研究了各种骨干网络(例如CNN和Transformer模型),以推广单目深度估计。首先,评估了分布内和分布外数据集上的SOTA模型,这在网络训练期间从未见过。然后,使用合成纹理移位数据集研究了基于CNN和Transformer的模型中间层表示的内部属性。通过大量实验,观察到transformer呈现出强烈的形状偏差,而CNN具有强烈纹理偏差。
2023最新 | 单目深度估计网络结构的通用性研究
|
传感器 机器学习/深度学习 人工智能
史上最全综述 | 3D目标检测算法汇总!(单目/双目/LiDAR/多模态/时序/半弱自监督)(下)
近年来,自动驾驶因其减轻驾驶员负担、提高行车安全的潜力而受到越来越多的关注。在现代自动驾驶系统中,感知系统是不可或缺的组成部分,旨在准确估计周围环境的状态,并为预测和规划提供可靠的观察结果。3D目标检测可以智能地预测自动驾驶车辆附近关键3D目标的位置、大小和类别,是感知系统的重要组成部分。本文回顾了应用于自动驾驶领域的3D目标检测的进展。
史上最全综述 | 3D目标检测算法汇总!(单目/双目/LiDAR/多模态/时序/半弱自监督)(下)
|
7月前
|
编解码 算法 自动驾驶
【计算机视觉】基于光流特征的目标跟踪算法LK光流法的讲解(图文解释 超详细)
【计算机视觉】基于光流特征的目标跟踪算法LK光流法的讲解(图文解释 超详细)
492 0
|
传感器 机器学习/深度学习 算法
【姿态解算】基于扩展卡尔曼滤波九轴传感器姿态解算研究附代码
【姿态解算】基于扩展卡尔曼滤波九轴传感器姿态解算研究附代码
|
机器学习/深度学习 算法 决策智能
计算机视觉实战(十六)光流估计 (附完整代码)
计算机视觉实战(十六)光流估计 (附完整代码)
205 0
|
机器学习/深度学习 存储
基于小脑模型神经网络的轨迹跟踪研究(Matlab代码实现)
基于小脑模型神经网络的轨迹跟踪研究(Matlab代码实现)
103 0
|
机器学习/深度学习 编解码 人工智能
2022最新 | 室外单目深度估计研究综述
原文首发微信公众号【自动驾驶之心】:一个专注自动驾驶与AI的社区(https://mp.weixin.qq.com/s/NK-0tfm_5KxmOfFHpK5mBA)
2022最新 | 室外单目深度估计研究综述
|
计算机视觉
UniMatch项目原作解读:统一光流、立体匹配和深度估计三个任务
UniMatch项目原作解读:统一光流、立体匹配和深度估计三个任务
176 0