0
点赞
收藏
分享

微信扫一扫

第八章 目标跟踪


第八章 目标跟踪

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

 






 

 

 

举报

相关推荐

0 条评论