为了账号安全,请及时绑定邮箱和手机立即绑定

我想在视频中定义一个感兴趣区域并只处理该区域

我想在视频中定义一个感兴趣区域并只处理该区域

幕布斯6054654 2022-01-11 17:20:44
我在理解 opencv 感兴趣的区域时遇到问题。我有一些代码可以从我的first_frame. 我还可以用我的mouse_draw_rect函数绘制一个矩形。现在,我希望背景减法只发生在我绘制的矩形内,因为我想加快算法处理速度。我知道我必须设置某种感兴趣的区域,但我昨天和今天都尝试了,但我从教程中尝试过的都没有奏效。有人可以帮助指导我完成这个过程吗?编辑:试图修复代码import numpy as npimport cv2import matplotlib.pyplot as pltcap = cv2.VideoCapture(0)_, first_frame = cap.read()def mouse_draw_rect(event, x, y, flags, params):    global point1, point2, drawing, first_frame, x1, x2, y1, y2    if event == cv2.EVENT_LBUTTONDOWN:        if drawing is False:            drawing = True            point1 = (x, y)            x1 = (x)            y1 = (y)        else:            drawing = False    elif event == cv2.EVENT_MOUSEMOVE:        if drawing is True:            point2 = (x, y)            x2 = (x)            y2 = (y)    elif event == cv2.EVENT_MBUTTONDOWN:        first_frame = framedrawing = Falsepoint1 = ()point2 = ()x1 = ()x2 = ()y1 = ()y2 = ()cv2.namedWindow('Original')cv2.setMouseCallback("Original", mouse_draw_rect)while True:    ret, frame = cap.read( )    if point1 and point2:        cv2.rectangle(frame, point1, point2, (0, 0, 0),5)    difference = cv2.absdiff(first_frame[y1:y2, x1:x2], frame[y1:y2, x1:x2])    difference = cv2.GaussianBlur(difference, (3, 3), 0)    _, difference = cv2.threshold(difference, 18, 255, cv2.THRESH_BINARY)    cv2.imshow('first frame (1)', first_frame)    cv2.imshow('Original', frame)    cv2.imshow('difference', difference)    key = cv2.waitKey(30) & 0xff    if key == 27:        breakcap.release()cv2.destroyAllWindows()
查看完整描述

2 回答

?
开满天机

TA贡献1786条经验 获得超13个赞

只需按您绘制的矩形区域进行裁剪。代替

difference = cv2.absdiff(first_frame, frame)

利用

difference = cv2.absdiff(first_frame[y1:y2, x1:x2], frame[y1:y2, x1:x2])


查看完整回答
反对 回复 2022-01-11
?
万千封印

TA贡献1891条经验 获得超3个赞

主要问题在于 ROI 选择事件以及当前如何调用它。当前的实现不是动态的,这意味着我们无法可视化我们正在尝试选择的 ROI。此外,我们甚至在选择 ROI 之前就已经开始处理。

选择 ROI 的正确方法是,一旦我们捕获了第一帧,注册鼠标单击事件并无限期地可视化该帧imshowwaitKey(n)直到按下某个特定键。或者,我们可以通过使用waitKey(0)(未测试)在没有无限循环的情况下实现相同的效果。

在这个阶段,我们应该能够绘制出想要的 ROI 矩形。这里的关键因素是必须通过使用无限循环或waitKey(0). 仅仅注册活动是不够的。完成 ROI 选择后,继续执行其余代码。

一些建议如下:

  • 尽可能避免使用全局变量

  • 为 ROI 选择创建单独的窗口,然后将其丢弃

  • 为每个单独的任务创建单独的函数

以下是演示正确使用鼠标单击事件来选择视频处理的 ROI 的完整代码:

import numpy as np

import cv2

import matplotlib.pyplot as plt



ORIGINAL_WINDOW_TITLE = 'Original'

FIRST_FRAME_WINDOW_TITLE = 'First Frame'

DIFFERENCE_WINDOW_TITLE = 'Difference'



canvas = None

drawing = False # true if mouse is pressed


#Retrieve first frame

def initialize_camera(cap):

    _, frame = cap.read()

    return frame



# mouse callback function

def mouse_draw_rect(event,x,y,flags, params):

    global drawing, canvas


    if drawing:

        canvas = params[0].copy()


    if event == cv2.EVENT_LBUTTONDOWN:

        drawing = True

        params.append((x,y)) #Save first point


    elif event == cv2.EVENT_MOUSEMOVE:

        if drawing:

            cv2.rectangle(canvas, params[1],(x,y),(0,255,0),2)


    elif event == cv2.EVENT_LBUTTONUP:

        drawing = False

        params.append((x,y)) #Save second point

        cv2.rectangle(canvas,params[1],params[2],(0,255,0),2)



def select_roi(frame):

    global canvas

    canvas = frame.copy()

    params = [frame]

    ROI_SELECTION_WINDOW = 'Select ROI'

    cv2.namedWindow(ROI_SELECTION_WINDOW)

    cv2.setMouseCallback(ROI_SELECTION_WINDOW, mouse_draw_rect, params)

    roi_selected = False

    while True:

        cv2.imshow(ROI_SELECTION_WINDOW, canvas)

        key = cv2.waitKey(10)


        #Press Enter to break the loop

        if key == 13:

            break;



    cv2.destroyWindow(ROI_SELECTION_WINDOW)

    roi_selected = (3 == len(params))


    if roi_selected:

        p1 = params[1]

        p2 = params[2]

        if (p1[0] == p2[0]) and (p1[1] == p2[1]):

            roi_selected = False


    #Use whole frame if ROI has not been selected

    if not roi_selected:

        print('ROI Not Selected. Using Full Frame')

        p1 = (0,0)

        p2 = (frame.shape[1] - 1, frame.shape[0] -1)



    return roi_selected, p1, p2





if __name__ == '__main__':


    cap = cv2.VideoCapture(0)


    #Grab first frame

    first_frame = initialize_camera(cap)


    #Select ROI for processing. Hit Enter after drawing the rectangle to finalize selection

    roi_selected, point1, point2 = select_roi(first_frame)    


    #Grab ROI of first frame

    first_frame_roi = first_frame[point1[1]:point2[1], point1[0]:point2[0], :]


    #An empty image of full size just for visualization of difference

    difference_image_canvas = np.zeros_like(first_frame)


    while cap.isOpened():


        ret, frame = cap.read()


        if ret:


            #ROI of current frame

            roi = frame[point1[1]:point2[1], point1[0]:point2[0], :]


            difference = cv2.absdiff(first_frame_roi, roi)

            difference = cv2.GaussianBlur(difference, (3, 3), 0)


            _, difference = cv2.threshold(difference, 18, 255, cv2.THRESH_BINARY)



            #Overlay computed difference image onto the whole image for visualization

            difference_image_canvas[point1[1]:point2[1], point1[0]:point2[0], :] = difference.copy()



            cv2.imshow(FIRST_FRAME_WINDOW_TITLE, first_frame)

            cv2.imshow(ORIGINAL_WINDOW_TITLE, frame)

            cv2.imshow(DIFFERENCE_WINDOW_TITLE, difference_image_canvas)



            key = cv2.waitKey(30) & 0xff

            if key == 27:

                break

        else:

            break


    cap.release()

    cv2.destroyAllWindows()

专业提示: 有时,在初始化相机时,根据房间内的环境光,它需要一些时间来预热。您可以考虑跳过一些初始帧,让相机从初始化阶段稳定下来。可以通过initialize_camera在上述代码中定义函数来完成,如下所示:


def initialize_camera(cap):

    for i in range(0,60): #Skip first 60 frames

        _, frame = cap.read()

    return frame


查看完整回答
反对 回复 2022-01-11
  • 2 回答
  • 0 关注
  • 153 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信