OpenCV Python 跟踪矩形不随视频中所选人物移动

问题描述 投票:0回答:1

我正在尝试跟踪出现在 YouTube 上的 53 秒视频中的某个人,如视频第 1 帧所示:


视频按价格 (2020) 中的第 1 帧

跟踪矩形(应该是)使用基于被跟踪者的 HSV 配置文件的 OpenCV 均值漂移函数。

不幸的是,帧中的红色矩形并没有真正随着视频中的人移动;它只是漫无目的地徘徊,最终停止移动。起初,我认为这是因为人朝相反的方向行走,因为该人比被跟踪的人更靠近观察者,这意味着当该人经过被跟踪的人时,跟踪矩形的“视图”被遮挡。随后我重写了代码,以便跟踪矩形从第 120 帧开始出现(以 30 fps 的速度进入视频 4 秒):


视频按价格 (2020) 中的第 120 帧

然而,这一行动并没有改善情况;事实上,矩形移动得更小!对象移动后,矩形在其位置停留几秒钟,然后漂移到墙壁的一部分并停留在那里。然后我认为这是因为矩形内的 HSV 轮廓包含背景。随后我缩小了矩形的大小,并确保其中的 HSV 轮廓排除了背景,如下所示:


视频按价格 (2020) 中的第 120 帧

这仍然没有什么区别。到目前为止,我一直在使用 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 日]。

python opencv video tracking
1个回答
0
投票

我终于解决了!

首先,我在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 似乎也有帮助!

允许微调,代码可以工作!

© www.soinside.com 2019 - 2024. All rights reserved.