OMES

?️ EVENTOS DEL MOUSE | OpenCV con Python

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

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.setMouseCallbacken 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:

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:
        cv2.circle(imagen,(x,y),20,(255,255,255),2)

    if event == cv2.EVENT_RBUTTONDOWN:
        cv2.circle(imagen,(x,y),20,(0,0,255),2)

    if event == cv2.EVENT_LBUTTONDBLCLK:
        cv2.circle(imagen,(x,y),10,(255,0,0),-1)

    if event == cv2.EVENT_RBUTTONDBLCLK:
        cv2.circle(imagen,(x,y),10,(0,255,0),-1)

    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.namedWindow('Imagen')
cv2.setMouseCallback('Imagen',dibujando)

while True:
    cv2.imshow('Imagen',imagen)
    
    k = cv2.waitKey(1) & 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 31: Creamos una imagen de ceros con 480 pixeles de alto, 640 de ancho y 3 canales. La imagen se verá así:

Figura 1: Visualización de la imagen de entrada.

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.

Figura 2: Visualización de los resultados obtenidos de dibujando_con_clics.py

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:

Figura 3: Imagen que se va a rotar según clics izquierdos o clics derechos

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 = cv2.warpAffine(imagen, M, (ancho,alto))

    if event == cv2.EVENT_RBUTTONDOWN:
        angulo = angulo - 15
        M = cv2.getRotationMatrix2D((ancho//2,alto//2), angulo, 1)
        imagen_a_rotar = cv2.warpAffine(imagen, M, (ancho,alto))

imagen = cv2.imread('ave.jpg')
imagen_a_rotar = imagen.copy() 
ancho = imagen.shape[1] # columnas
alto = imagen.shape[0]  # filas
angulo = 0
cv2.namedWindow('imagen_a_rotar')
cv2.setMouseCallback('imagen_a_rotar',rotar)

while True:
    #cv2.imshow('Imagen',imagen)
    cv2.imshow('imagen_a_rotar',imagen_a_rotar)
    print('Ángulo=',angulo)
    if cv2.waitKey(1) & 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.

NOTA: Recuerda que las funcionescv2.getRotationMatrix2D y cv2.warpAffine las habíamos tratado en el post: ?️ Como trasladar, rotar, escalar y recortar una imagen | Python – OpenCV

Línea 16 a 20: Leemos la imagen de entrada, realizamos una copia de ella que se almacenará en imagen_a_rotar, luego procedemos a obtener el ancho y alto de la imagen de entrada. En la línea 20 declaramos la variable angulo que se modificará conforme se presione el botón derecho o izquierdo del mouse.

Línea 21 y 22: Asignamos un nombre a la ventana de donde se tomarán los eventos del mouse, y luego aplicamos la función cv2.setMouseCallback que llamará a la función rotar, previamente creada.

Línea 24 a 31: Visualizamos imagen_a_rotar, imprimimos el ángulo que tengamos en ese momento en consola y si presionamos ESC, el proceso terminará.

Veamos los resultados:

Figura 4: Rotación de la imagen cuando se presiona el botón izquierdo del mouse.

 

Figura 5: Rotación de la imagen cuando se presiona el botón derecho del mouse.

Como podemos apreciar en las figuras 4 y 5, hemos cumplido con el objetivo de rotar una imagen en sentido horario o antihorario dependiendo de los clics derechos o izquierdos.

Y hasta aquí llega el tutorial de hoy, espero que te haya gustado ?. ¡Nos vemos en un siguiente video/post tutorial!.

Referencias

Salir de la versión móvil