Поток управления Python OpenCv: почему cv2.setMouseCallback не находится внутри l oop? - PullRequest
1 голос
/ 01 апреля 2020

Я запутался с потоком управления в следующей программе. Цель кода - нарисовать прямоугольник в прямом эфире видео с веб-камеры.

Принцип работы: первый щелчок будет инициализировать координаты начального угла прямоугольника и пометить его жирным кружком. Второй щелчок завершит прямоугольник.

Теперь мой вопрос: почему оператор cv2.setMouseCallback ('Test', draw_rectangle) не находится внутри l oop?

Код работает отлично, но я не могу понять поток управления. Пожалуйста, помогите мне.

    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()

Ответы [ 3 ]

1 голос
/ 01 апреля 2020

Функции обратного вызова вызываются на события. В отличие от обычной функции, вам не нужно вызывать функцию каждый раз, когда вы хотите, чтобы она выполнялась.

Строка cv2.setMouseCallback('Test',draw_rectangle) установит функцию draw_rectangle в качестве ответа на любое событие, полученное от мыши в окне OpenCV "Test". Как только обратный вызов установлен, внутри вашего while l oop вы поймаете все события мыши в окне "Test".

1 голос
/ 01 апреля 2020

cv2.setMouseCallback ('Test', draw_rectangle) эта функция на самом деле является обработчиком событий, который устанавливает вызов функции draw_rectangle при каждом щелчке левой кнопкой мыши. Остальная часть кода внутри while l oop предназначена для всех динамических операций c, и, наконец, cv2.imshow должен отобразить это в образе.

Один токен подарка для лучшей обработки opencv закрыть Windows, закрывая только используемое в данный момент окно:

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)
1 голос
/ 01 апреля 2020

Обратный вызов - это функция, которая вызывается каждый раз, когда вы наводите указатель мыши на окно дисплея. Он не зависит от потока в main, т. Е. Находится в новом потоке, ожидая изменений в вводе мышью.

Причина, по которой вы используете l oop в main, заключается в том, что вы хотите обновить изображение, которое вы отобразить. После вызова imshow вам нужно позвонить waitKey для влияния на рендеринг.

...