【问题标题】:Flow of Control Python OpenCv : Why cv2.setMouseCallback isn't inside loop?控制流 Python OpenCv:为什么 cv2.setMouseCallback 不在循环内?
【发布时间】:2020-04-01 20:09:38
【问题描述】:

我对以下程序中的控制流程感到困惑。代码的目的是在来自网络摄像头的实时视频流中绘制一个矩形。

工作原理:第一次单击将初始化矩形起始角的坐标,并用粗体圆圈标记它。第二次单击将完成矩形。

现在我的问题是:为什么 cv2.setMouseCallback('Test',draw_rectangle) 语句不在循环内?

代码运行良好,但我无法理解控制流程。请帮帮我。

    import cv2
    import os
    os.environ["OPENCV_VIDEOIO_PRIORITY_MSMF"] = "0" 


#CALLBACK FUNCTION RECTANGLE
def draw_rectangle(event,x,y,flags,param):  #Param is the just the additional paramter which u can receive
    global pt1, pt2, topLeft_Clicked, botRight_Clicked
    if event ==cv2.EVENT_LBUTTONDOWN:

        #Reset if rectangle is drawing i.e both var are true
        if topLeft_Clicked and botRight_Clicked:
            pt1=(0,0)
            pt2=(0,0)
            topLeft_Clicked=False
            botRight_Clicked=False
        if topLeft_Clicked == False:   
            pt1=(x,y)
            topLeft_Clicked=True
        elif  botRight_Clicked == False:
            pt2=(x,y)
            botRight_Clicked=True



#GLOBAL VARIABLES
pt1=(0,0)
pt2=(0,0)

topLeft_Clicked= False
botRight_Clicked= False

#COnnect to the Callback
cap=cv2.VideoCapture(0)
cv2.namedWindow('Test')
cv2.setMouseCallback('Test',draw_rectangle)
while True:

    ret,frame=cap.read()

    #Drawing Based on Global Variables

    if topLeft_Clicked: # If topleft is true
        cv2.circle(frame,center=pt1,radius=5,color=(0,0,255),thickness=-1)

    if topLeft_Clicked and botRight_Clicked:
        cv2.rectangle(frame,pt1,pt2,(0,0,255),3)

    cv2.imshow('Test',frame)

    if(cv2.waitKey(1) & 0xFF==ord('q')):
        break

cap.release()
cv2.destroyAllWindows()

【问题讨论】:

    标签: opencv image-processing jupyter-notebook opencv-python


    【解决方案1】:

    回调函数在事件上被调用。与常规函数不同,您不需要每次希望它运行时都进行函数调用。

    cv2.setMouseCallback('Test',draw_rectangle) 行将设置函数draw_rectangle 作为对从 OpenCV 窗口"Test" 上的鼠标接收到的任何事件的响应。设置回调后,在 while 循环中,您将在 "Test" 窗口中捕获所有鼠标事件。

    【讨论】:

      【解决方案2】:

      回调是每次将鼠标移到显示窗口上时调用的函数。它独立于 main 中的流程,即它在一个新线程中等待鼠标输入的变化。

      你之所以在 main 中使用循环是因为你想更新你显示的图像。调用imshow后,需要调用waitKey对渲染的影响。

      【讨论】:

        【解决方案3】:

        cv2.setMouseCallback('Test',draw_rectangle) 这个函数实际上是一个事件处理程序,它设置每次鼠标左击时对draw_rectangle函数的调用。 while 循环中的其余代码用于所有动态操作,最后 cv2.imshow 将其渲染到图像中。

        为了更好地处理 opencv closeWindows,只关闭当前使用的窗口:

        def showImage(imageName, image):
            img = image.copy()
            cv2.imshow(imageName, img)
            while(1):
                pressedKey = cv2.waitKey(0) & 0xFF
        
                if(pressedKey == ord('q')):
                    cv2.destroyWindow(imageName)
                    break
                else:
                    cv2.putText(img, "\press q to exit", (10,10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color=(255,0,0))
                    cv2.imshow(imageName, img)
        

        【讨论】:

          猜你喜欢
          • 2018-04-17
          • 2018-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-07
          • 2021-07-10
          • 1970-01-01
          相关资源
          最近更新 更多