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
.
JavaScript
x
53
53
1
import sys
2
import math
3
4
import cv2
5
6
7
class DrawCircle:
8
def __init__(self):
9
self.p1 = None
10
self.p2 = None
11
self.clicked = False
12
13
def __call__(self, img):
14
self.img = img
15
self.redraw()
16
return self.p1, self.p2
17
18
def redraw(self):
19
drawn = self.img.copy()
20
if self.p1 is not None and self.p2 is not None:
21
center = (int(round((self.p1[0] + self.p2[0]) / 2)),
22
int(round((self.p1[1] + self.p2[1]) / 2)))
23
radius = int(math.sqrt(
24
(self.p1[0] - self.p2[0])**2 + (self.p1[1] - self.p2[1])**2) / 2)
25
cv2.circle(drawn, center, radius, (0, 0, 255), thickness=1)
26
window_name = 'draw circle'
27
cv2.imshow(window_name, drawn)
28
cv2.setMouseCallback(window_name, self._on_mouse_interact)
29
k = cv2.waitKey(0)
30
if k == ord('q'):
31
cv2.destroyAllWindows()
32
return
33
34
def _on_mouse_interact(self, event, x, y, flags, param):
35
if event == cv2.EVENT_LBUTTONDOWN:
36
self.clicked = True
37
self.p1 = [x, y]
38
self.p2 = None
39
if event == cv2.EVENT_MOUSEMOVE:
40
if self.clicked:
41
self.p2 = [x, y]
42
self.redraw()
43
if event == cv2.EVENT_LBUTTONUP:
44
self.clicked = False
45
self.p2 = [x, y]
46
self.redraw()
47
48
49
if __name__ == '__main__':
50
draw_tool = DrawCircle()
51
img = cv2.imread(sys.argv[1])
52
draw_tool(img)
53
It can be run with
JavaScript
1
2
1
python script.py path/to/image/file
2
My issue is that I get
JavaScript
1
7
1
Traceback (most recent call last):
2
File "utils/realtime_draw.py", line 47, in _on_mouse_interact
3
self.redraw()
4
File "utils/realtime_draw.py", line 24, in redraw
5
drawn = self.img.copy()
6
RecursionError: maximum recursion depth exceeded while calling a Python object
7
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:
JavaScript
1
54
54
1
import sys
2
import math
3
4
import cv2
5
6
7
class DrawCircle:
8
def __init__(self):
9
self.p1 = None
10
self.p2 = None
11
self.clicked = False
12
13
def __call__(self, img):
14
self.img = img
15
self.window_name = 'draw circle'
16
cv2.imshow(self.window_name, self.img)
17
cv2.setMouseCallback(self.window_name, self._on_mouse_interact)
18
self.redraw()
19
k = cv2.waitKey(0)
20
if k == ord('q'):
21
cv2.destroyAllWindows()
22
return
23
return self.p1, self.p2
24
25
def redraw(self):
26
drawn = self.img.copy()
27
if self.p1 is not None and self.p2 is not None:
28
center = (int(round((self.p1[0] + self.p2[0]) / 2)),
29
int(round((self.p1[1] + self.p2[1]) / 2)))
30
radius = int(math.sqrt(
31
(self.p1[0] - self.p2[0])**2 + (self.p1[1] - self.p2[1])**2) / 2)
32
cv2.circle(drawn, center, radius, (0, 0, 255), thickness=1)
33
cv2.imshow(self.window_name, drawn)
34
35
def _on_mouse_interact(self, event, x, y, flags, param):
36
if event == cv2.EVENT_LBUTTONDOWN:
37
self.clicked = True
38
self.p1 = [x, y]
39
self.p2 = None
40
if event == cv2.EVENT_MOUSEMOVE:
41
if self.clicked:
42
self.p2 = [x, y]
43
self.redraw()
44
if event == cv2.EVENT_LBUTTONUP:
45
self.clicked = False
46
self.p2 = [x, y]
47
self.redraw()
48
49
50
if __name__ == '__main__':
51
draw_tool = DrawCircle()
52
img = cv2.imread(sys.argv[1])
53
draw_tool(img)
54
Could you please check, whether that works for you?