What should be the arguments of cv2.setMouseCallback()

Muhammad Abdullah picture Muhammad Abdullah · Nov 4, 2017 · Viewed 15k times · Source

I have been working on opencv and have passed through cv2.setMouseCallback() . Following is the code for drawing circles on mouse click .
import cv2 import numpy as np

def draw_circle(event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
    cv2.circle(image,(x,y),(100,100),(255,0,0),-1)
img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow("image")
cv2.setMouseCallback("image",draw_circle)

while True:
    cv2.imshow("image",image)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break
cv2.destroyAllWindows()`

please explain

  1. How can function draw_circle can be called without passing all his arguments
  2. there are five arguments in function and there are only two variables which can be assigned values
  3. what is the purpose of creating cv2.namedWindow("image")

THANKS!

Answer

Dani picture Dani · May 5, 2018
  1. You don't call draw_circle, openCV will call it for you on a mouse event with the proper event and coordinates, you just specify which function to be called for what window in setMouseCallback

  2. if you need additional variables you can send them via param

  3. You can have multiple windows with a different mouse action set for each one

I hope this example can be helpful for someone who stumbles across :

import cv2
import numpy as np
from math import sqrt

def calc_distance(p1, p2):
    (x1, y1) = p1
    (x2, y2) = p2
    return round(sqrt((x1-x2)**2 + (y1-y2)**2))

# param contains the center and the color of the circle 
def draw_red_circle(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDBLCLK:
        center = param[0]
        radius = calc_distance((x, y), center)
        cv2.circle(img, center, radius, param[1], 2)


def draw_blue_circle(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDBLCLK:
        center = (100,100)
        radius = calc_distance((x, y), center)     
        cv2.circle(img, center, radius, (255, 0, 0), 2)

img = np.zeros((512,512,3), np.uint8)

# create 2 windows
cv2.namedWindow("img_red")
cv2.namedWindow("img_blue")

# different doubleClick action for each window
# you can send center and color to draw_red_circle via param
param = [(200,200),(0,0,255)]
cv2.setMouseCallback("img_red", draw_red_circle, param)
cv2.setMouseCallback("img_blue", draw_blue_circle) # param = None


while True:
    # both windows are displaying the same img
    cv2.imshow("img_red", img)
    cv2.imshow("img_blue", img)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break
cv2.destroyAllWindows()