OpenCV 行人跟踪

CAMShift

OpenCV提供了CamShift函数用于目标跟踪. 其全称为Continuously Adaptive Meanshift是由Gary Bradsky于1988年提出的,论文为”Computer Vision Face Tracking for Use in a Perceptual User Interface”.

CamShift是基于MeanShift算法的,相较MeanShift能够动态调整追踪窗口的大小,将上一帧作为下一帧追踪计算的初始值,效果更好.

CamShift计算前需要首先进行以下步骤:

  1. 将RGB图像转换为HSV图像;

  2. 计算图像直方图,并归一化,得到Color probability Image;

  3. 设置CamShift参数.

然后在每帧执行以下步骤:

  1. 将RGB图像转换为HSV图像;

  2. 计算BackProject;

  3. 计算CamShift.

CamShift在OpenCV中的函数形式为

1
2
3
4
# C++
RotatedRect CamShift(InputArray probImage, Rect& window, TermCriteria criteria)
# Python
cv2.CamShift(probImage, window, criteria) → retval, window

其参数如下.

参数 含义
probImage Back projection of the object histogram. See calcBackProject()
window Initial search window
criteria Stop criteria for the underlying meanShift()

人体追踪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/usr/local/bin/python
# -*- coding: UTF-8 -*-
import cv2
import numpy as np

def is_inside(o, i):# 判断o是否在i外的函数
ox, oy, ow, oh = o
ix, iy, iw, ih = i
return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih

def detect_person(image):# 检测被追踪的人体的函数
ret, img=capture.read() #按帧读取视频 ret-帧状态布尔值,img-图像矩阵
hog = cv2.HOGDescriptor()# 创建HOGDescriptor对象
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())# 使用OpenCV预训练好的人体识别检测器
found, w = hog.detectMultiScale(img)# 构造了图像金字塔和滑窗,进行检测
print ("w=")
print (w)
found_filtered = []# 存储检测目标
for ri, r in enumerate(found):
for qi, q in enumerate(found):
if ri != qi and is_inside(r, q):
break
else:
found_filtered.append(r)
# for person in found_filtered:
return found_filtered # 返回检测到的人体的位置


capture = cv2.VideoCapture(0) #打开视频,参数为路径;参数为0表示打开笔记本的内置摄像头
print capture.isOpened() #显示打开是否成功
while (1): # 由于有时画面中无法检测出人体,需要循环直到找到人体后再跳出循环
ret, frame = capture.read() #先获取第一帧 ret-帧状态布尔值,img-图像矩阵
found_filtered = detect_person(frame)
if (len(found_filtered) != 0 ):
break # 跳出while 循环
c,r,w,h = found_filtered[0] # 此处仅跟踪了一个人体,实际应该考虑画面中有多个人的情况
track_window = c,r,w,h # 人体在画面中的位置范围
roi = frame[r:r+h, c:c+w]
hsv_roi = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 转换为HSV图
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]) # 计算Histogram
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX) # Histogram归一化
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 ) # 准备CamShift
while(1):
ret ,frame = capture.read()
if ret == True:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 转换HSV图
dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1) # BackProject
ret, track_window = cv2.CamShift(dst, track_window, term_crit)# Camshift方法-物体追踪
pts = cv2.boxPoints(ret)
pts = np.int0(pts)
img2 = cv2.polylines(frame,[pts],True, 255,2)
cv2.imshow('Tracked Person',img2)
key=cv2.waitKey(1) #等待键盘输入,间隔1ms waits for a key event infinitely (when [delay]< 0 ) or for [delay] milliseconds,
if key == 27 : #ESC键的ASCII码
print "detect ESC"
break #退出while循环
capture.release() #释放笔记本摄像头
cv2.destroyAllWindows() #关闭所有图像窗口

运行结果

识别摄像头采集图像中的人体并实时跟踪,效果如下.

20190604113526.png

由于人体识别的算法效果一般,且CamShift的跟踪效果也不太好,经常会出现初始人体识别错误导致跟踪的不是人体 或 跟踪一段时间后突然跟踪到其它相邻物体的情况.

该算法有待进一步改进.

0%