OpenCV  4.1.0
Open Source Computer Vision
Mouse as a Paint-Brush

Goal

Simple Demo

Here, we create a simple application which draws a circle on an image wherever we double-click on it.

First we create a mouse callback function which is executed when a mouse event take place. Mouse event can be anything related to mouse like left-button down, left-button up, left-button double-click etc. It gives us the coordinates (x,y) for every mouse event. With this event and location, we can do whatever we like. To list all available events available, run the following code in Python terminal:

1 import cv2 as cv
2 events = [i for i in dir(cv) if 'EVENT' in i]
3 print( events )

Creating mouse callback function has a specific format which is same everywhere. It differs only in what the function does. So our mouse callback function does one thing, it draws a circle where we double-click. So see the code below. Code is self-explanatory from comments :

1 import numpy as np
2 import cv2 as cv
3 
4 # mouse callback function
5 def draw_circle(event,x,y,flags,param):
6  if event == cv.EVENT_LBUTTONDBLCLK:
7  cv.circle(img,(x,y),100,(255,0,0),-1)
8 
9 # Create a black image, a window and bind the function to window
10 img = np.zeros((512,512,3), np.uint8)
11 cv.namedWindow('image')
12 cv.setMouseCallback('image',draw_circle)
13 
14 while(1):
15  cv.imshow('image',img)
16  if cv.waitKey(20) & 0xFF == 27:
17  break

More Advanced Demo

Now we go for a much better application. In this, we draw either rectangles or circles (depending on the mode we select) by dragging the mouse like we do in Paint application. So our mouse callback function has two parts, one to draw rectangle and other to draw the circles. This specific example will be really helpful in creating and understanding some interactive applications like object tracking, image segmentation etc.

1 import numpy as np
2 import cv2 as cv
3 
4 drawing = False # true if mouse is pressed
5 mode = True # if True, draw rectangle. Press 'm' to toggle to curve
6 ix,iy = -1,-1
7 
8 # mouse callback function
9 def draw_circle(event,x,y,flags,param):
10  global ix,iy,drawing,mode
11 
12  if event == cv.EVENT_LBUTTONDOWN:
13  drawing = True
14  ix,iy = x,y
15 
16  elif event == cv.EVENT_MOUSEMOVE:
17  if drawing == True:
18  if mode == True:
19  cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
20  else:
21  cv.circle(img,(x,y),5,(0,0,255),-1)
22 
23  elif event == cv.EVENT_LBUTTONUP:
24  drawing = False
25  if mode == True:
26  cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
27  else:
28  cv.circle(img,(x,y),5,(0,0,255),-1)

Next we have to bind this mouse callback function to OpenCV window. In the main loop, we should set a keyboard binding for key 'm' to toggle between rectangle and circle.

1 img = np.zeros((512,512,3), np.uint8)
2 cv.namedWindow('image')
3 cv.setMouseCallback('image',draw_circle)
4 
5 while(1):
6  cv.imshow('image',img)
7  k = cv.waitKey(1) & 0xFF
8  if k == ord('m'):
9  mode = not mode
10  elif k == 27:
11  break
12 

Additional Resources

Exercises

  1. In our last example, we drew filled rectangle. You modify the code to draw an unfilled rectangle.