我正在尝试跟踪出现在 YouTube 上的 53 秒视频中的某个人,如视频第 1 帧所示:
跟踪矩形(应该是)使用基于被跟踪者的 HSV 配置文件的 OpenCV 均值漂移函数。
不幸的是,帧中的红色矩形并没有真正随着视频中的人移动;它只是漫无目的地徘徊,最终停止移动。起初,我认为这是因为人朝相反的方向行走,因为该人比被跟踪的人更靠近观察者,这意味着当该人经过被跟踪的人时,跟踪矩形的“视图”被遮挡。随后我重写了代码,以便跟踪矩形从第 120 帧开始出现(以 30 fps 的速度进入视频 4 秒):
然而,这一行动并没有改善情况;事实上,矩形移动得更小!对象移动后,矩形在其位置停留几秒钟,然后漂移到墙壁的一部分并停留在那里。然后我认为这是因为矩形内的 HSV 轮廓包含背景。随后我缩小了矩形的大小,并确保其中的 HSV 轮廓排除了背景,如下所示:
这仍然没有什么区别。到目前为止,我一直在使用 OpenCV 的按位和直方图函数来推断矩形内区域的 HSV 范围。但直方图是 2D 的,我只在分析中包含 H 和 S,并将 V 的范围设置为 0 到 255。之后,我使用 3D Matplotlib 并获得了更精确的 V 范围,以配合精确的 H 和 S 范围。跟踪尝试的最终代码如下:
import cv2 as cv
import numpy as np
import time
source = 'A quiet Japanese street.mp4' # https://www.youtube.com/watch?v=gbsMx0cyM34
capture = cv.VideoCapture('bank_videos/' + source)
start = time.time()
RED = (0, 0, 255)
# Set up initial location of window
x, y, w, h = 180, 261, 10, 14
track_window = (x, y, w, h)
# Set up the ROI for tracking
roi = frame[y:y+h, x:x+w]
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((105, 10, 0)), np.array((145, 80, 80)))
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
# I wondered if the 5th argument for cv.calcHist() should be [0, 180, 0, 256]
# but this raised an exception
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# Set up the termination criteria, either 10 iteration or move by at least 1 pt
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
while capture.isOpened():
ret, frame = capture.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
else:
# Convert BGR to HSV
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)
if int(time.time() - start) in range(4, 27):
# Draw tracking rectangle
cv.rectangle(frame, (x,y), (x+w,y+h), RED,2)
# Apply meanshift to get the new location
ret, track_window = cv.meanShift(dst, track_window, term_crit)
cv.imshow('Frame', frame)
if cv.waitKey(27) == ord('q'):
break
然而,这并没有产生任何影响。那么,我哪里出错了?与
cv.waitKey()
的论点有关吗?我不这么认为。矩形没有响应主体的移动,我不明白为什么。
(如果您想知道,我正在使用 Jupyter Notebook,并且
capture.release()
和 cv.destroyAllWindows()
出现在单独的后续单元格中。)
参考
Price, A.(2020)一条安静的日本街道。来源:https://www.youtube.com/watch?v=gbsMx0cyM34 [访问日期:2024 年 2 月 25 日]。
我终于解决了!
首先,我在while循环之前没有定义
ret, frame
。 (未引发异常的原因是因为这两个变量已在之前的单元格中定义 - 请记住,我正在使用 Jupyter Notebook。)
其次,跟踪矩形太小,因此当人移动时,HSV 属性最终会移出我在其中设置的狭窄范围,可能很快。更大的矩形允许其中的 HSV 属性发生更渐进的变化。
因此,最终代码为:
# ... First part of code ...
start = time.time()
RED = (0, 0, 255)
x, y, w, h = 161, 201, 40, 92 # Bigger rectangle
track_window = (x, y, w, h)
# Set up the ROI for tracking
ret, frame = capture.read() # ret,frame defined here
roi = frame[y:y+h, x:x+w]
# ... More code ...
while capture.isOpened():
ret, frame = capture.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
else:
# Convert BGR to HSV
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)
if int(time.time() - start) in range(4, 20):
# Apply meanshift to get the new location
ret, track_window = cv.meanShift(dst, track_window, term_crit)
# Draw tracking rectangle
x, y, w, h = track_window
cv.rectangle(frame, (x,y), (x+w,y+h), RED,2)
cv.imshow('Frame', frame)
if cv.waitKey(12) == ord('q'):
break
此外,将
cv.waitKey()
的参数从 27 更改为 12 似乎也有帮助!
允许微调,代码可以工作!