OpenCV mouse action monitoring

cv2.setMouseCallback(winname, MouseCallback) is a monitoring function for the mouse status of the winname window. When there is a mouse action on the winname window, that is Automatically calling the MouseCallback function is equivalent to a mouse interrupt for this window. Before this function, there should be a corresponding window declaration function cv2.namedWindow(winname) to be captured by the setMouseCallback() function to confirm the operation window.

?# Callback function definition
def MouseCallback(event, x, y, flags, param):
    # Left mouse button pressed
    if event == cv.EVENT_LBUTTONDOWN:
        print("EVENT_LBUTTONDOWN")
    # Right mouse button press
    elif event == cv.EVENT_RBUTTONDOWN:
        print("EVENT_RBUTTONDOWN")
"""
MouseCallback(event:int,x:int,y:int,flags:int,ustc:None)
event: mouse event enumeration
x: x coordinate of mouse event occurrence
y: The y coordinate where the mouse event occurs
flags: mouse drag status
"""

Event correspondence table:

Events

Means

EVENT_MOUSEMOVE

mouse movement

EVENT_LBUTTONDOWN

left click

EVENT_RBUTTONDOWN

right click

EVENT_MBUTTONDOWN

middle click

EVENT_LBUTTONUP

Release the left button

EVENT_RBUTTONUP

Right click and release

EVENT_MBUTTONUP

Release the middle button

EVENT_LBUTTONDBLCLK

Double left click

EVENT_RBUTTONDBLCLK

Right double click

EVENT_MBUTTONDBLCLK

Middle-click double-click

Status correspondence table:

Flags

Means

EVENT_FLAG_LBUTTON

Left click drag

EVENT_FLAG_RBUTTON

Right click and drag

EVENT_FLAG_MBUTTON

Middle button drag

EVENT_FLAG_CTRLKEY

Press Ctrl

EVENT_FLAG_SHIFTKEY

Press Shift

EVENT_FLAG_ALTKEY

Press Alt

?# Window declaration
cv2.namedWindow('drawing')
# Mouse event binding
cv2.setMouseCallback('drawing', MouseCallback)
"""
cv2.setMouseCallback(winname:str,MouseCallback,userdata = 0)
winname: image window name
MouseCallback: Mouse response function name, called after monitoring mouse operations and processing the corresponding actions
userdata: ID and identification number of the mouse response processing function (optional)
"""

*If you want to use the mouse to draw graphics on a dynamic video, the drawing operation cannot be placed in the callback function, because the image will always be updated and displayed, and the new image will immediately overwrite the old image. If you do this, although the callback function will still be executed, the drawn image will still not be visible. Since the callback function cannot be called directly, in order to draw such an image, you can set global variables to transmit the callback information location and mouse events.

The following code can realize that after the mouse clicks on a point on the image, a solid point is drawn at that point, and the (x, y) coordinates of this point relative to the image are displayed on the image.

# Drawing point experiment
#Import OpenCV package
import cv2 as cv
# Define global variables
point = (-1,-1)
#Write callback function
def action(event, x, y, flags, param):
    global point
    # Left mouse button pressed
    if event == cv.EVENT_LBUTTONDOWN:
#Left click to update global variables
        point = (x, y)
        print("EVENT_LBUTTONDOWN")
        print(x, ' ', y)

# Window declaration
cv.namedWindow('drawing')
# Mouse event binding
cv.setMouseCallback('drawing', action)
camera = cv.VideoCapture(0)
while True:
    s, img = camera.read()
# Draw the image at the specified location through global variables
    cv.circle(img,point,4,(0,0,255),-1)
    cv.putText(img,f"{point}",point,cv.FONT_HERSHEY_TRIPLEX,1,(0,0,255),1)
    cv.imshow('drawing', img)
    # Press q key to exit
    if cv.waitKey(1) & 0xFF == ord('q'):
        break
camera.release()
cv.destroyAllWindows()

Through the technology of mouse action monitoring, we can make a simple color picker, which can display the color of the selected pixel in a new window by right-clicking and display its BGR value. The implementation code is as follows:

# Color picker
#Import opencv and numpy
import cv2
import numpy
# Define window width and window height
W = 320
H = 240
#x,y coordinates of the current click position
click_x = -1
click_y = -1
#Define mouse callback function
def action(event,x,y,flags,pramer):
    global click_x
    global click_y
    # Click the left and right buttons to update the click coordinate value
    if event == cv2.EVENT_LBUTTONDOWN or event == cv2.EVENT_RBUTTONDOWN:
        click_x = x
        click_y = y
    # Right click and select colors
    if event == cv2.EVENT_RBUTTONDOWN:
        #Create an array to receive the color matrix of type numpy.uint8 with
        img1 = numpy.zeros((H, W, 3),numpy.uint8)
        b = img[y, x, 0]
        g = img[y, x, 1]
        r = img[y, x, 2]
        img1[:, : ] = [b,g,r]
        # Distinguish the background color and text color, pay attention to the type conversion from uint8 to int
        text_color = (255 - int(b),255 - int(g),255 - int(r))
        # Display the current BGR value
        cv2.putText(img1, f"{img[click_y, click_x, 0], img[click_y, click_x, 1], img[click_y, click_x, 2]}", (0, 20),cv2.FONT_HERSHEY_PLAIN, 1, text_color, 1)
        cv2.imshow('img1', img1)
        cv2.moveWindow("img1", W, 0)

#Declare the window in advance
cv2.namedWindow("camera")
# Mouse event binding
cv2.setMouseCallback("camera",action)
camera = cv2.VideoCapture(0)
while True:
    s,img = camera.read()
    #Reset image width and height
    img = cv2.resize(img,(W,H))
    # Click the position to draw the point
    cv2.circle(img,tuple([click_x,click_y]),1,(0,0,255),-1)
    # Click to display the location coordinates
    cv2.putText(img, f"{click_x, click_y}", tuple([click_x, click_y]), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 1)
    cv2.imshow('camera', img)
    cv2.moveWindow("camera", 0, 0)
    
    key_event = cv2.waitKey(1)
    if key_event == ord('q'):
        break
        
camera.release()
cv2.destroyAllWindows()