I have a class for opening up an image and drawing circles. The entire code can be found here:
p1
and p2
store diametrically opposing points on a circle. These are capture with click and drag actions in _on_mouse_interact
.
import sys import math import cv2 class DrawCircle: def __init__(self): self.p1 = None self.p2 = None self.clicked = False def __call__(self, img): self.img = img self.redraw() return self.p1, self.p2 def redraw(self): drawn = self.img.copy() if self.p1 is not None and self.p2 is not None: center = (int(round((self.p1[0] + self.p2[0]) / 2)), int(round((self.p1[1] + self.p2[1]) / 2))) radius = int(math.sqrt( (self.p1[0] - self.p2[0])**2 + (self.p1[1] - self.p2[1])**2) / 2) cv2.circle(drawn, center, radius, (0, 0, 255), thickness=1) window_name = 'draw circle' cv2.imshow(window_name, drawn) cv2.setMouseCallback(window_name, self._on_mouse_interact) k = cv2.waitKey(0) if k == ord('q'): cv2.destroyAllWindows() return def _on_mouse_interact(self, event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: self.clicked = True self.p1 = [x, y] self.p2 = None if event == cv2.EVENT_MOUSEMOVE: if self.clicked: self.p2 = [x, y] self.redraw() if event == cv2.EVENT_LBUTTONUP: self.clicked = False self.p2 = [x, y] self.redraw() if __name__ == '__main__': draw_tool = DrawCircle() img = cv2.imread(sys.argv[1]) draw_tool(img)
It can be run with
python script.py path/to/image/file
My issue is that I get
Traceback (most recent call last): File "utils/realtime_draw.py", line 47, in _on_mouse_interact self.redraw() File "utils/realtime_draw.py", line 24, in redraw drawn = self.img.copy() RecursionError: maximum recursion depth exceeded while calling a Python object
Where is the recursion here?
Advertisement
Answer
Found some time… Apparently, it’s the waitKey
stuff. I moved some lines from the redraw
to the __call__
, and now, I don’t get the error anymore:
import sys import math import cv2 class DrawCircle: def __init__(self): self.p1 = None self.p2 = None self.clicked = False def __call__(self, img): self.img = img self.window_name = 'draw circle' cv2.imshow(self.window_name, self.img) cv2.setMouseCallback(self.window_name, self._on_mouse_interact) self.redraw() k = cv2.waitKey(0) if k == ord('q'): cv2.destroyAllWindows() return return self.p1, self.p2 def redraw(self): drawn = self.img.copy() if self.p1 is not None and self.p2 is not None: center = (int(round((self.p1[0] + self.p2[0]) / 2)), int(round((self.p1[1] + self.p2[1]) / 2))) radius = int(math.sqrt( (self.p1[0] - self.p2[0])**2 + (self.p1[1] - self.p2[1])**2) / 2) cv2.circle(drawn, center, radius, (0, 0, 255), thickness=1) cv2.imshow(self.window_name, drawn) def _on_mouse_interact(self, event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: self.clicked = True self.p1 = [x, y] self.p2 = None if event == cv2.EVENT_MOUSEMOVE: if self.clicked: self.p2 = [x, y] self.redraw() if event == cv2.EVENT_LBUTTONUP: self.clicked = False self.p2 = [x, y] self.redraw() if __name__ == '__main__': draw_tool = DrawCircle() img = cv2.imread(sys.argv[1]) draw_tool(img)
Could you please check, whether that works for you?