Search code examples
pythonopencvmouseevent

mouse events on opencv


I am trying to write a function which will open an image and draw a circle where the left mouse button is clicked. the circle's size can then be adjusted using the mousewheel/keyboard. Also, every click will print a label in sequence e.g. 1st circle puts label '1', 2nd circle drawn puts a label'2' and so on. I have managed to get the circle and the label on the image but i am unsure how to increase the radius or change the label with different clicks.

import cv2
import numpy as np

# Create a black image and a window
windowName = 'Drawing'
img = cv2.imread('000025.png',cv2.IMREAD_COLOR)
cv2.namedWindow(windowName)








# mouse callback function
def draw_circle(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img, (x,y), 30, (255, 0,), 1)
        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(img,'label' , (x + 30, y + 30), font, 1, (200, 255, 155), 1, cv2.LINE_AA)




# bind the callback function to window
cv2.setMouseCallback(windowName, draw_circle)


def main():
    while (True):
        cv2.imshow(windowName, img)
        if cv2.waitKey(20) == 27:
            break

    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

Solution

  • Using the following code you can visualize the circle while moving the mouse as well. I have supplemented the code provided by Salman by adding another condition involving MOUSEMOVE event.

    import cv2
    import numpy as np
    import math
    
    drawing = False
    
    def draw_circle(event, x, y, flags, param):
        global x1, y1, drawing, radius, num, img, img2
        if event == cv2.EVENT_LBUTTONDOWN:
            drawing = True
            x1, y1 = x, y
            radius = int(math.hypot(x - x1, y - y1))
            cv2.circle(img, (x1,y1), radius, (255, 0, 0), 1)
    
        elif event == cv2.EVENT_MOUSEMOVE:
            if drawing == True:
                a, b = x, y
                if a != x & b != y:
                    img = img2.copy()
                    radius = int(math.hypot(a - x1, b - y1))
                    cv2.circle(img, (x1,y1), radius, (255, 0, 0), 1)
    
        elif event == cv2.EVENT_LBUTTONUP:
            drawing = False
            num += 1
            radius = int(math.hypot(x - x1, y - y1))
            cv2.circle(img, (x1,y1), radius, (255, 0, 255), 1)
            font = cv2.FONT_HERSHEY_SIMPLEX
            cv2.putText(img, '_'.join(['label', str(num)]), (x + 20, y + 20), font, 1, (200, 255, 155), 1, cv2.LINE_AA)
            img2 = img.copy()
    
    
    if __name__ == "__main__":
        num = 0
        windowName = 'Drawing'
    
        img = np.zeros((500, 500, 3), np.uint8)
        img2 = img.copy()
        cv2.namedWindow(windowName)
        cv2.setMouseCallback(windowName, draw_circle)
        while (True):
            cv2.imshow(windowName, img)
            if cv2.waitKey(20) == 27:
                break
    
        cv2.destroyAllWindows()
    

    Sample output:

    enter image description here