Problem: I want the code to exit the loop once a rectangle is drawn but it's not working! I have a loop with cv.waitKey() waiting to be pressed. How can I exit the loop from some external initiator? I am building off of someone else's code btw.
I tried using pynput but for some reason it isn't working... Here is the code and I would like to exit the while loop once the rectangle is drawn on the image.
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()
-it is executing the pynput keypress (I know since it prints 'pressed'), but it isn't producing any effect on the code. sad.
Thank you for the helppppp! ~(^ \_`_/ ^)~
Instead of implicitly breaking the loop through key commands, I think it is better and more Pythonic to use flags, i.e. boolean variables that tell you when to run or to break a loop. This is especially easy for you since you are working with an instantiated object, that is an instance that shares the same scope among its methods (through the self
parameter).
For example, in your __init__()
function, you can initialize a variable self.loop_running = True
, which is defined upon instantiation.
Subsequently, in your draw()
method, set this flag to False
whenever you want to trigger a loop break, example:
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
Then in your final function where you call the main loop, change while True
to while self.loop_running
instead!:
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