Te doy la bienvenida a un nuevo post. Hace unos días, un lector de este blog me había consultado como usar el ratón para con OpenCV rotar una imagen cierto ángulo en sentido horario o antihorario, dependiendo claro del botón del mouse que se esté presionando. Esto me recordó que no había hablado aún sobre los eventos del mouse, es decir el como podemos tomar acciones hechas por el mouse y añadirles algún proceso usando OpenCV. Por ello en el post de hoy desarrollaremos este tema y al final también veremos como resolver el problema planteado por el lector.
CONTENIDO
Eventos del Mouse con OpenCV y Python cv2.setMouseCallback Ejemplo para obtener los eventos del mouse con OpenCV Explorando cada uno de los eventos del mouse cv2.EVENT_MOUSEMOVE cv2.EVENT_LBUTTONDOWN cv2.EVENT_RBUTTONDOWN cv2.EVENT_MBUTTONDOWN cv2.EVENT_LBUTTONUP cv2.EVENT_RBUTTONUP cv2.EVENT_MBUTTONUP cv2.EVENT_LBUTTONDBLCLK cv2.EVENT_RBUTTONDBLCLK cv2.EVENT_MBUTTONDBLCLK cv2.EVENT_MOUSEWHEEL cv2.EVENT_MOUSEHWHEEL Resultados obtenidos cada vez que se presionan los botones del mouse (línea 13 a 29) Resolviendo a la pregunta: ¿Cómo usar el ratón con OpenCV para rotar una imagen cierto ángulo en sentido horario o antihorario?
Eventos del Mouse con OpenCV y Python
OpenCV nos permite detectar acciones que realiza el ratón o mouse sobre una imagen, tales como: movimiento del puntero en la pantalla, clic, doble clic, desplazamientos (scrolling), entre otros. Permitiéndonos añadir procesos cuando estas acciones se realicen.
cv2.setMouseCallback
En la programación para detectar las acciones realizadas por el ratón necesitamos de la función cv2.setMouseCallback, en ella en primer lugar debemos especificar el nombre de la ventana de donde se van a obtener los eventos y como segundo argumento la función de devolución de llamada para eventos. Esta última debe contar con los siguientes parámetros:
event , una de las constantes MouseEventTypes: cv2.EVENT_MOUSEMOVE = 0, indica que el puntero del mouse se ha movido por la ventana. cv2.EVENT_LBUTTONDOWN = 1, indica que el botón izquierdo del mouse es presionado. cv2.EVENT_RBUTTONDOWN = 2, indica que el botón derecho del mouse es presionado. cv2.EVENT_MBUTTONDOWN = 3, indica que el botón central del mouse es presionado. cv2.EVENT_LBUTTONUP = 4, indica que se suelta el botón izquierdo del ratón. cv2.EVENT_RBUTTONUP = 5, indica que se suelta el botón derecho del ratón. cv2.EVENT_MBUTTONUP = 6, indica que se suelta el botón central del ratón. cv2.EVENT_LBUTTONDBLCLK = 7, indica que se hace doble clic en el botón izquierdo del ratón. cv2.EVENT_RBUTTONDBLCLK = 8, indica que se hace doble clic en el botón derecho del ratón. cv2.EVENT_MBUTTONDBLCLK = 9, indica que se hace doble clic en el botón central del ratón. cv2.EVENT_MOUSEWHEEL = 10, desplazamiento (scrolling) del ratón adelante y atrás. cv2.EVENT_MOUSEHWHEEL = 11, desplazamiento (scrolling) del ratón izquierda y derecha.
, una de las constantes MouseEventTypes: x , la coordenada x del evento del mouse.
, la coordenada x del evento del mouse. y , la coordenada y del evento del mouse.
, la coordenada y del evento del mouse. flags , una de las constantes MouseEventFlags: cv2.EVENT_FLAG_LBUTTON = 1, indica que el botón izquierdo del mouse está presionado. cv2.EVENT_FLAG_RBUTTON = 2, indica que el botón derecho del mouse está presionado. cv2.EVENT_FLAG_MBUTTON = 4, indica que el botón central del mouse está presionado. cv2.EVENT_FLAG_CTRLKEY = 8, indica que la tecla CTRL está presionada. cv2.EVENT_FLAG_SHIFTKEY = 16, indica que la tecla SHIFT está presionada. EVENT_FLAG_ALTKEY = 32, indica que la tecla ALT está presionada.
, una de las constantes MouseEventFlags: userdata, parámetro opcional.
Cabe destacar que podrías usar combinaciones entre MouseEventTypes y MouseEventFlags.
Ejemplo para obtener los Eventos del mouse con OpenCV
A continuación te mostraré un programa, en el cual se están empleando los eventos del mouse para dibujar círculos, circunferencias y texto sobre una imagen. En esta ocasión usaremos 6 eventos, pero no te preocupes que exploraremos los demás imprimiendo los valores de event, x, y y flags. Lo importante es principalmente entender como se emplean.
Vamos a crear el programa llamado: dibujando_con_clics.py
import cv2 import numpy as np def dibujando(event,x,y,flags,param): # Imprimimos la información sobre los eventos que se estén realizando print('-----------------------------') print('event=',event) print('x=',x) print('y=',y) print('flags=',flags) # Ejemplos de acciones con algunos eventos del mouse if event == cv2.EVENT_LBUTTONDOWN: if event == cv2.EVENT_RBUTTONDOWN: if event == cv2.EVENT_LBUTTONDBLCLK: if event == cv2.EVENT_RBUTTONDBLCLK: if event == cv2.EVENT_LBUTTONUP: cv2.putText(imagen,'Ha dejado de presionar (Izquierdo)',(x,y),2,0.4,(255,255,0),1,cv2.LINE_AA) if event == cv2.EVENT_RBUTTONUP: cv2.putText(imagen,'Ha dejado de presionar (Derecho)',(x,y),2,0.4,(0,255,255),1,cv2.LINE_AA) imagen = np.zeros((480,640,3),np.uint8) cv2.setMouseCallback('Imagen',dibujando) while True: cv2.imshow('Imagen',imagen) k = & 0xFF if k == ord('l'): # Limpiar el contenido de la imagen imagen = np.zeros((480,640,3),np.uint8) elif k == 27: break cv2.destroyAllWindows()
Línea 1 y 2: Importamos OpenCV y numpy.
Línea 4 a 29: Creamos una función llamada dibujando, que nos servirá para detectar cada uno de los eventos del mouse, veamos más a profundidad esta función:
Línea 7 a 10: Imprimimos los valores de event, x, y y flags, con esto conseguiremos explorar cada uno de los eventos y banderas, al momento de realizar acciones con el mouse sobre la imagen.
Imprimimos los valores de event, x, y y flags, con esto conseguiremos explorar cada uno de los eventos y banderas, al momento de realizar acciones con el mouse sobre la imagen. Línea 13 y 14: Si event es igual a cv2.EVENT_LBUTTONDOWN , es decir si se ha dado un clic izquierdo, entonces se dibujará una circunferencia de color blanco con radio 20 en la ubicación (x,y) , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el clic.
Si es igual a , es decir si se ha dado un clic izquierdo, entonces se dibujará una circunferencia de color blanco con radio 20 en la ubicación , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el clic. Línea 16 y 17: Si event es igual a cv2.EVENT_RBUTTONDOWN , es decir si se ha dado un clic derecho, entonces se dibujará una circunferencia de color rojo con radio 20 en la ubicación (x,y) , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el clic.
Si es igual a , es decir si se ha dado un clic derecho, entonces se dibujará una circunferencia de color rojo con radio 20 en la ubicación , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el clic. Línea 19 y 20: Si event es igual a cv2.EVENT_LBUTTONDBLCLK , es decir si se ha dado doble clic izquierdo, entonces se dibujará un círculo de color azul con radio 10 en la ubicación (x,y) , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el doble clic.
Si es igual a , es decir si se ha dado doble clic izquierdo, entonces se dibujará un círculo de color azul con radio 10 en la ubicación , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el doble clic. Línea 22 y 23: Si event es igual a cv2.EVENT_RBUTTONDBLCLK , es decir si se ha dado doble clic derecho, entonces se dibujará un círculo de color verde con radio 10 en la ubicación (x,y) , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el doble clic.
Si es igual a , es decir si se ha dado doble clic derecho, entonces se dibujará un círculo de color verde con radio 10 en la ubicación , que corresponde a la ubicación del puntero sobre la imagen al momento de realizar el doble clic. Línea 25 y 26: Si event es igual a cv2.EVENT_LBUTTONUP , es decir si se ha soltado el botón izquierdo del ratón, entonces se visualizará 'Ha dejado de presionar (Izquierdo)' en color celeste, en la ubicación (x,y) , que corresponde a la ubicación en donde se ha dejado de presionar el botón izquierdo.
Si es igual a , es decir si se ha soltado el botón izquierdo del ratón, entonces se visualizará en color celeste, en la ubicación , que corresponde a la ubicación en donde se ha dejado de presionar el botón izquierdo. Línea 28 y 29: Si event es igual a cv2.EVENT_RBUTTONUP , es decir si se ha soltado el botón derecho del ratón, entonces se visualizará 'Ha dejado de presionar (Derecho)' en color amarillo, en la ubicación (x,y) , que corresponde a la ubicación en donde se ha dejado de presionar el botón derecho.
Línea 31: Creamos una imagen de ceros con 480 pixeles de alto, 640 de ancho y 3 canales. La imagen se verá así:
Línea 32: Asignamos un nombre a la ventana de la cual extraeremos los eventos del mouse.
Línea 33: Dentro de cv2.setMouseCallback especificamos como primer argumento el nombre de la ventana que habíamos realizado en la línea 32, y como segundo argumento la función dibujando que está entre las líneas 4 y 29.
Línea 35 a 36: Visualizamos la imagen contenida en la variable image , toma en cuenta que el nombre de la ventana es el mismo usado en las líneas 32 y 33.
Línea 39 y 40: Si se presiona la tecla l, se limpiará todo el contenido dibujado por los eventos del mouse.
Línea 41 y 42: Si se presiona ESC, el ciclo se romperá y el programa terminará.
Explorando cada uno de los eventos del mouse
Antes de pasar con los resultados obtenidos cada vez que se presionan los botones del mouse (línea 13 a 29) veamos los valores obtenidos con cada uno de los tipos de eventos realizados por el ratón, es decir estaremos examinando los valores obtenidos de las líneas 7 a 10.
Para estas pruebas estaremos ejecutando el script dibujando_con_clics.py
cv2.EVENT_MOUSEMOVE
Este evento se presenta al momento que el mouse se mueve en la imagen (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 0 # Corresponde a cv2.EVENT_MOUSEMOVE x= 211 # Ubicación del puntero en la coordenada x y= 192 # Ubicación del puntero en la coordenada y flags= 0
cv2.EVENT_LBUTTONDOWN
Se da cuando el botón izquierdo es presionado (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 1 # Corresponde a cv2.EVENT_LBUTTONDOWN x= 204 # Ubicación del puntero en la coordenada x y= 233 # Ubicación del puntero en la coordenada y flags= 1 # Corresponde a cv2.EVENT_FLAG_LBUTTON
cv2.EVENT_RBUTTONDOWN
Indica que el botón derecho es presionado (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 2 # Corresponde a cv2.EVENT_RBUTTONDOWN x= 108 # Ubicación del puntero en la coordenada x y= 355 # Ubicación del puntero en la coordenada y flags= 2 # Corresponde a cv2.EVENT_FLAG_RBUTTON
cv2.EVENT_MBUTTONDOWN
Indica que el botón central es presionado (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 3 # Corresponde a cv2.EVENT_MBUTTONDOWN x= 108 # Ubicación del puntero en la coordenada x y= 355 # Ubicación del puntero en la coordenada y flags= 4 # Corresponde a cv2.EVENT_FLAG_MBUTTON
cv2.EVENT_LBUTTONUP
Indica que se suelta el botón izquierdo del ratón (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 4 # Corresponde a cv2.EVENT_LBUTTONUP x= 208 # Ubicación del puntero en la coordenada x y= 304 # Ubicación del puntero en la coordenada y flags= 0
cv2.EVENT_RBUTTONUP
Indica que se suelta el botón derecho del ratón (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 5 # Corresponde a cv2.EVENT_RBUTTONUP x= 208 # Ubicación del puntero en la coordenada x y= 304 # Ubicación del puntero en la coordenada y flags= 0
cv2.EVENT_MBUTTONUP
Indica que se suelta el botón central del ratón (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 6 # Corresponde a cv2.EVENT_MBUTTONUP x= 108 # Ubicación del puntero en la coordenada x y= 355 # Ubicación del puntero en la coordenada y flags= 0
cv2.EVENT_LBUTTONDBLCLK
Indica que se hace un doble clic en el botón izquierdo del ratón (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 7 # Corresponde a cv2.EVENT_LBUTTONDBLCLK x= 282 # Ubicación del puntero en la coordenada x y= 215 # Ubicación del puntero en la coordenada y flags= 1 # Corresponde a cv2.EVENT_FLAG_LBUTTON
cv2.EVENT_RBUTTONDBLCLK
Indica que se hace un doble clic en el botón derecho del ratón (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 8 # Corresponde a cv2.EVENT_RBUTTONDBCLK x= 282 # Ubicación del puntero en la coordenada x y= 215 # Ubicación del puntero en la coordenada y flags= 2 # Corresponde a cv2.EVENT_FLAG_RBUTTON
cv2.EVENT_MBUTTONDBLCLK
Indica que se hace un doble clic en el botón central del ratón (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 9 # Corresponde a cv2.EVENT_MBUTTONDBLCLK x= 108 # Ubicación del puntero en la coordenada x y= 355 # Ubicación del puntero en la coordenada y flags= 4 # Corresponde a cv2.EVENT_FLAG_MBUTTON
cv2.EVENT_MOUSEWHEEL
Desplazamiento (scrolling) del ratón adelante y atrás (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 10 # Corresponde a cv2.EVENT_MOUSEWHEEL x= 154 # Ubicación del puntero en la coordenada x y= 230 # Ubicación del puntero en la coordenada y flags= -131072 # Valores positivos o negativos de acuerdo al movimiento
cv2.EVENT_MOUSEHWHEEL
Desplazamiento (scrolling) del ratón izquierda y derecha (los valores de x e y pueden cambiar dependiendo de la ubicación del puntero).
event= 11 # Corresponde a cv2.EVENT_MOUSEWHEEL x = 420 # Ubicación del puntero en la coordenada x y= 239 # Ubicación del puntero en la coordenada y flags= 131072 # Valores positivos o negativos de acuerdo al movimiento
Resultados obtenidos cada vez que se presionan los botones del mouse (línea 13 a 29)
Ahora que hemos explorado cada uno de los eventos del mouse, pasemos a los resultados de las acciones de los eventos que programamos. Para ello daré clics derechos e izquierdos sobre la imagen.
Como vemos, en la parte izquierda de la imagen, tenemos una circunferencia blanca que indica que el botón izquierdo del ratón ha sido presionado, mientras que más abajo tenemos el mensaje Ha dejado de presionar (Izquierdo), que es la ubicación en donde se ha dejado de presionar el botón. Finalmente tenemos un círculo azul que indica que se ha realizado un doble clic en el botón izquierdo, como consecuencia se ha dibujado también la circunferencia y el mensaje.
En la parte derecha de la imagen, tenemos una circunferencia roja que indica que el botón derecho del ratón ha sido presionado, mientras que debajo se muestra el mensaje Ha dejado de presionar (Derecho), que es la ubicación en donde se ha dejado de presionar el botón. Finalmente tenemos un círculo verde que indica que se ha realizado un doble clic en el botón derecho, como consecuencia se ha dibujado también la circunferencia y el mensaje.
Resolviendo a la pregunta: ¿Cómo usar el ratón con OpenCV para rotar una imagen cierto ángulo en sentido horario o antihorario?
Ya vimos como trabajan los eventos del mouse con OpenCV. Por lo que voy a responder a la duda que el lector de este blog me había planteado. Para ello, dada una imagen, esta rotará 15° grados en sentido horario o en sentido antihorario dependiendo si se presiona el botón izquiero o derecho del ratón respectivamente. Usaremos la siguiente imagen:
Para este programa crearemos un programa llamado: rotando_con_clics.py
import cv2 def rotar(event,x,y,flags,param): global angulo, imagen_a_rotar if event == cv2.EVENT_LBUTTONDOWN: angulo = angulo + 15 M = cv2.getRotationMatrix2D((ancho//2,alto//2), angulo, 1) imagen_a_rotar = M, (ancho,alto)) if event == cv2.EVENT_RBUTTONDOWN: angulo = angulo - 15 M = cv2.getRotationMatrix2D((ancho//2,alto//2), angulo, 1) imagen_a_rotar = M, (ancho,alto)) imagen = cv2.imread('ave.jpg') imagen_a_rotar = ancho = imagen.shape[1] # columnas alto = imagen.shape[0] # filas angulo = 0 cv2.setMouseCallback('imagen_a_rotar',rotar) while True: #cv2.imshow('Imagen',imagen) cv2.imshow('imagen_a_rotar',imagen_a_rotar) print('Ángulo=',angulo) if & 0xFF == 27: break cv2.destroyAllWindows()
Línea 1: Importamos OpenCV.
Línea 3 a 14: Creamos la función rotar que nos servirá para detectar los eventos del mouse.
Línea 4: Tomamos las variables angulo e imagen_a_rotar .
Tomamos las variables e . Línea 6 a 9: Si se presiona el botón izquierdo del mouse, entonces la variable angulo incrementará su valor y gracias a cv2.getRotationMatrix2D y la imagen rotará en sentido horario.
Si se presiona el botón izquierdo del mouse, entonces la variable incrementará su valor y gracias a y la imagen rotará en sentido horario. Línea 11 a 14: Si se presiona el botón derecho del mouse, entonces la variable angulo disminuirá su valor, luego aplicamos las funciones cv2.getRotationMatrix2D y de tal modo que la imagen rotará en sentido antihorario.
NOTA: Recuerda que las funciones cv2.getRotationMatrix2D y las habíamos tratado en el post: