Как я могу заставить эту программу запускать cv.waitKey () самостоятельно для выхода из этого цикла? - PullRequest
0 голосов
/ 11 июля 2019

Проблема: Я хочу, чтобы код вышел из цикла, как только нарисован прямоугольник, но он не работает!У меня есть цикл с cv.waitKey () в ожидании нажатия.Как выйти из цикла из какого-то внешнего инициатора?Кстати, я строю чужой код.

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

import numpy as np
import cv2 as cv
from pynput.keyboard import Key, Controller
from time import sleep



class Interface:

    def __init__(self, image):

        self.ix = 0
        self.iy = 0
        self.ix2 = 0
        self.iy2 = 0
        self.drawing = False
        self.before_rect = image.copy()
        self.image = image.copy()
        self.result_img = image.copy()

    # Adding Function Attached To Mouse Callback
    def draw(self,event,x,y,flags,params):

        # Left Mouse Button Down Pressed
        if(event==1):
            self.drawing = True
            self.ix = x
            self.iy = y
        # Moving mouse
        if(event==0):
            self.ix2 = x
            self.iy2 = y
            if self.drawing == True:
                self.image = (self.before_rect).copy()
                cv.rectangle(self.image, pt1=(self.ix, self.iy), pt2=(x, y), color=(255, 255, 255), thickness=3)
        # Left Mouse Button Up
        if(event==4):
            if self.drawing == True:
                self.ix2 = x
                self.iy2 = y
                # For Drawing Rectangle
                cv.rectangle(self.result_img, pt1=(self.ix, self.iy), pt2=(x, y), color=(255, 255, 255), thickness=3)
                self.image = (self.result_img).copy()


                '''Here is the issue!!! How do I solve it?'''

                # Doesn't do anything to exit the loop like I wanted :(
                print('pressed') # (output to terminal) -> pressed 
                keyboard = Controller()
                keyboard.press(Key.esc)
                sleep(.01)
                keyboard.release(Key.esc)

            self.drawing = False

    def get_boxes(self):

        cv.namedWindow("Window")

        # Adding Mouse CallBack Event
        cv.setMouseCallback("Window", self.draw)

        # Starting The Loop So Image Can Be Shown
        while (True):
            cv.imshow("Window", self.image)
            if cv.waitKey(5) & 0xFF == 27:
                break
        cv.destroyAllWindows()

        return


# Making The Blank Image
orig = np.zeros((512,512,3))

# Start drawing boxes!
obj = Interface(orig)
obj.get_boxes()

- он выполняет нажатие клавиши pynput (я знаю, так как он печатает «нажатыми»), но это не оказывает никакого влияния на код.грустный.

Спасибо за помощь! ~ (^ \ _`_ / ^) ~

1 Ответ

0 голосов
/ 11 июля 2019

Использовать логические флаги

Вместо того, чтобы неявно прерывать цикл с помощью ключевых команд, я думаю, что лучше и более Pythonic использовать flags , то есть логические переменные, которые сообщают вам, когда запускать илиразорвать петлю.Это особенно легко для вас, так как вы работаете с экземпляром объекта, то есть экземпляром, который имеет ту же область видимости среди своих методов (через параметр self).

Например, в вашем __init__()Функция, вы можете инициализировать переменную self.loop_running = True, которая определяется при создании экземпляра.

Впоследствии, в вашем методе draw(), установите этот флаг на False всякий раз, когда вы захотите вызвать разрыв цикла, например:

def drawing(*args):
    # some code
    if self.drawing:
        self.ix2 = x
        self.iy2 = y
        # For Drawing Rectangle
        cv.rectangle(self.result_img, pt1=(self.ix, self.iy), pt2=(x, y), color=(255, 255, 255), thickness=3)
        self.image = (self.result_img).copy()
        # set flag to false ->
        self.loop_running = False

Затем в вашей последней функции, в которой вы вызываете основной цикл, измените вместо while True на while self.loop_running!:

def get_boxes(self):

    cv.namedWindow("Window")

    # Adding Mouse CallBack Event
    cv.setMouseCallback("Window", self.draw)

    # Starting The Loop So Image Can Be Shown
    while self.loop_running:
        cv.imshow("Window", self.image)
    cv.destroyAllWindows()

    return
...