“This is the 28th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

Draw dynamically using mouse events

We’ve heard a lot about drawing graphics and text using OpenCV. In this article, we will learn how to perform dynamic drawing using mouse events using drawing functions in OpenCV.

Dynamic drawing

In order to do dynamic drawing with mouse events, we must first understand how to handle mouse events with OpenCV, using the cv2.setMousecallBack () function in OpenCV. This function is used as follows:

cv2.setMouseCallback(windowName, onMouse, param=None)
Copy the code

This function creates a mouse handler for a window named windowName. The onMouse function is a callback that is called when a mouse event occurs (for example, a double click, a left click, a left click, and so on). The optional param argument is used to pass additional information to the callback function. So, to handle mouse events, the first step is to create a callback function:

def draw_circle(event, x, y, flags, param) :
    if event == cv2.EVENT_LBUTTONDBLCLK:
        print("event: EVENT_LBUTTONDBLCLK")
        cv2.circle(image, (x, y), 20, colors['magenta'] -1)

    if event == cv2.EVENT_MOUSEMOVE:
        
        print("event: EVENT_MOUSEMOVE")

    if event == cv2.EVENT_LBUTTONUP:
        print("event: EVENT_LBUTTONUP")

    if event == cv2.EVENT_LBUTTONDOWN:
        print("event: EVENT_LBUTTONDOWN")
        cv2.rectangle(image,(x,y),(x+20,y+20),colors['cyan'].1)
Copy the code

The draw_circle() function receives the coordinates (x, y) of a particular event and each mouse event. When left-clicking (cv2.event_lButtondBLclk), we draw a circle at the corresponding (x, y) coordinates of the event. When left-clicking (cv2.event_lbuttonDown) is performed, a square is drawn at the corresponding (x, y) coordinates. In addition, we print some messages to view other generated events, but we don’t use them to do anything else for the time being.

Next, create a naming window and name it Mouse Event. This named window will be associated with the mouse callback function:

cv2.namedWindow('Image mouse')
Copy the code

Finally, set the mouse callback function to the one we created earlier:

cv2.setMouseCallback('Image mouse', draw_circle)
Copy the code

At this point, when the left mouse click is performed, a filled magenta circle is drawn around the (x, y) position of the performed double click, and a square is drawn at the corresponding (x, y) coordinates when the left mouse click is performed.

Dynamically draw graphics and text

In this practical program, graphics and text will be dynamically drawn with mouse events. First, draw text to show how to use mouse events to perform a particular action:

def draw_text() :
    # We set the position to be used for drawing text:
    menu_pos = (10.540)
    menu_pos2 = (10.555)
    menu_pos3 = (10.570)
    menu_pos4 = (10.585)

    Draw text to show how to use mouse events to perform specific actions
    cv2.putText(image, 'Double left click: add a circle', menu_pos, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255.255.255))
    cv2.putText(image, 'Simple right click: delete last circle', menu_pos2, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255.255.255))
    cv2.putText(image, 'Double right click: delete all circle', menu_pos3, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255.255.255))
    cv2.putText(image, 'Press \'q\' to exit', menu_pos4, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255.255.255))
Copy the code

From the above code, we know that the code needs to do the following:

  1. Use double click to add a circle and display the center coordinates
  2. Use the right click to remove the last added circle
  3. Delete all circles with a double – click right-click

To implement these capabilities, we first create a list called Circles, where we maintain the current circles drawn by the user. In addition, we used render text to create backup images. When the mouse event is generated, we add or remove circles and text from the circle list. Later, when drawing, we only draw the current circle and its center text in the list, and when the user right-clicks, the last added circle is removed from the list.

def draw_circle(event, x, y, flags, param) :
    global circles
    if event == cv2.EVENT_LBUTTONDBLCLK:
        # Add the center coordinates to the list
        print("event: EVENT_LBUTTONDBLCLK")
        circles.append((x, y))

    if event == cv2.EVENT_RBUTTONDBLCLK:
        Delete all circles
        print("event: EVENT_RBUTTONDBLCLK")
        circles[:] = []
    elif event == cv2.EVENT_RBUTTONDOWN:
        # Remove the last added circle
        print("event: EVENT_RBUTTONDOWN")
        try:
            circles.pop()
        except (IndexError):
            print("no circles to delete")
    if event == cv2.EVENT_MOUSEMOVE:
        print("event: EVENT_MOUSEMOVE")
    if event == cv2.EVENT_LBUTTONUP:
        print("event: EVENT_LBUTTONUP")
    if event == cv2.EVENT_LBUTTONDOWN:
        print("event: EVENT_LBUTTONDOWN")
Copy the code