Lab15 - Event Mouse
Objetivos da aula:
- apresentar e aplicar o Event click do mouse
QUAL O PROBLEMA?
Não é bem um problema mas pode ser util em alguns casos saber interagir na imagem com o mouse para fazer um recorte da imaem, saber o RGB de um pixel ou encontrar um angulo entre retas. Sabemos fazer isso sem mouser, mas gastamos um tempinho para fazer todos os ajustes...
Visualmente é simples essa tarefa, basta clicar com o mouse na região escolhida e pronto!.
## vou fazer o download das imagens do repositório para usar no colab mais facil....
!wget https://raw.githubusercontent.com/arnaldojr/cognitivecomputing/master/material/aulas/PDI/lab15/admiravelmundonovo.jpg /content
!wget https://raw.githubusercontent.com/arnaldojr/cognitivecomputing/master/material/aulas/PDI/lab15/transferidor.jpg /content
Event Mouse¶
Podemos criar uma interface gráfica e interatividade com o mouse, nesse caso, baseado em eventos.
Toda a vez que ocorre um evento do mouse, uma função de callback é executada no código.
Vamos ver isso funcionado no código.
Lembrete: No notebook pode travar, é melhor rodar em um arquivo .py
import cv2
import numpy as np
#
# cria uma matriz (imagem) de 480x640 com 3 canais (r,g,b), img toda preta com maximos de 0-255
img = np.zeros((480, 640, 3), dtype="uint8")
# exibe a img
cv2.imshow('image', img)
# é uma função de callback para tratativa de eventos do mouse
def mouse_click(event, x, y, flags, param):
# se foi click do botao direito
if event == cv2.EVENT_RBUTTONDOWN:
# faça a função....
pass
if event == cv2.EVENT_LBUTTONDOWN:
# faça a função....
pass
# configura o evento do mouse e chama a função mouse_click
cv2.setMouseCallback('image', mouse_click)
cv2.waitKey(0)
#
cv2.destroyAllWindows()
2024-04-01 11:53:22.997 Python[30860:5062868] WARNING: Secure coding is automatically enabled for restorable state! However, not on all supported macOS versions of this application. Opt-in to secure coding explicitly by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState:.
O código acima cria uma imagem preta e fica aguardando um evento do mouse. O mouse pode gerar alguns tipos de eventos, mas quais são eles???
# Dica python como usar um list comprehensions no python e a função built-in dir()
import cv2
import numpy as np
# A função dir() devolte todas propriedades e métodos de um objeto especifico
#print(len(dir(cv2)))
#print (dir(cv2))
# Vamos varrer o objeto cv2 e filtrar apenas os métodos que tem relação com EVENT
eventos = []
for i in dir(cv2):
if 'EVENT' in i:
eventos.append(i)
print(eventos)
print(len(eventos))
# Usando List comprehension
# Devolve uma lista na variavel events filtando os dados de outra lista
#events = [i for i in dir(cv2) if 'EVENT' in i]
#print( events )
['EVENT_FLAG_ALTKEY', 'EVENT_FLAG_CTRLKEY', 'EVENT_FLAG_LBUTTON', 'EVENT_FLAG_MBUTTON', 'EVENT_FLAG_RBUTTON', 'EVENT_FLAG_SHIFTKEY', 'EVENT_LBUTTONDBLCLK', 'EVENT_LBUTTONDOWN', 'EVENT_LBUTTONUP', 'EVENT_MBUTTONDBLCLK', 'EVENT_MBUTTONDOWN', 'EVENT_MBUTTONUP', 'EVENT_MOUSEHWHEEL', 'EVENT_MOUSEMOVE', 'EVENT_MOUSEWHEEL', 'EVENT_RBUTTONDBLCLK', 'EVENT_RBUTTONDOWN', 'EVENT_RBUTTONUP'] 18
Basicamente são esses:
Eventos:
CV_EVENT_MOUSEMOVE: movimento do mouse
CV_EVENT_LBUTTONDOWN: Pressione o botão esquerdo do mouse
CV_EVENT_RBUTTONDOWN: Pressione o botão direito do mouse
CV_EVENT_MBUTTONDOWN: Pressione o botão do meio do mouse
CV_EVENT_LBUTTONUP: solte o botão esquerdo
CV_EVENT_RBUTTONUP: solte o botão direito
CV_EVENT_MBUTTONUP: Solte o botão do meio
CV_EVENT_LBUTTONDBLCLK: clique duplo esquerdo
CV_EVENT_RBUTTONDBLCLK: Clique duplo direito
CV_EVENT_MBUTTONDBLCLK: clique duplo do botão do meio
CV_EVENT_MOUSEWHEEL: Mova o mouse para frente (+) ou para trás (-)
CV_EVENT_MOUSEHWHEEL: Mova o mouse para a direita (+) ou esquerda (-)
Flags:
CV_EVENT_FLAG_LBUTTON: Clique com o botão esquerdo e arraste
CV_EVENT_FLAG_RBUTTON: Clique com o botão direito e arraste
CV_EVENT_FLAG_MBUTTON: botão do meio arrastar
CV_EVENT_FLAG_CTRLKEY: Pressione e segure Ctrl
CV_EVENT_FLAG_SHIFTKEY: shift pressione e segure
CV_EVENT_FLAG_ALTKEY: pressione e segure alt
Desafio 1¶
O nosso código está funcionando mas, note que não mandamos realizar nenhum ação na chamada do callback.
Implemente um código que troca a cor da imagem a cada click.
import cv2
import numpy as np
# Carrega uma imagem
# Neste caso estamos criando uma imagem RGB preta de tamanho 480x640
img = np.zeros((480, 640, 3), dtype="uint8")
# Exibe a imagem
cv2.imshow('image', img)
# Função de callback, quando ocorre um evento do mouse, essa função é chamada
def mouse_click(event, x, y, flags, param):
global img
# Se foi o botão esquerdo do mouse
# Se foi o botão direito do mouse
if event == cv2.EVENT_RBUTTONDOWN:
# ---------- implemente a solução...
img[:,:] = [255,0,0]
cv2.imshow('image', img)
# Se foi o botão direito do mouse
if event == cv2.EVENT_LBUTTONDBLCLK:
# ---------- implemente a solução...
img[:,:] = [0,0,255]
cv2.imshow('image', img)
# Seta a função de callback que será chamada
# Evento 'image', função callback mouse_click
cv2.setMouseCallback('image', mouse_click)
cv2.waitKey(0)
# fecha a janela.
cv2.destroyAllWindows()
Projeto 1¶
Vamos criar o nosso proprio color picker.
Ao clicar sobre a imagem, aparece a intensidade do pixel em RGB.
import cv2
import numpy as np
# Carrega uma imagem
img = cv2.imread('admiravelmundonovo.jpg')
# Exibe a imagem
cv2.imshow('image', img)
# Função de callback, quando ocorre um evento do mouse, essa função é chamada
def mouse_click(event, x, y, flags, param):
# Se foi o botão esquerdo do mouse
if event == cv2.EVENT_LBUTTONDOWN:
# Realiza função...
#blue = img[y,x,0]
#green = img[y,x,1]
#red = img[y,x,2]
blue, green, red = img[y,x]
#print (red, green, blue)
msg = "R:" + str(red) + ", G:" + str(green) + ", B:" +str(blue)
cv2.putText(img,msg,(x,y),cv2.FONT_HERSHEY_COMPLEX,1.5,(255,255,255),2)
cv2.imshow('image', img)
# Seta a função de callback que será chamada
# Evento 'image', função callback mouse_click
cv2.setMouseCallback('image', mouse_click)
cv2.waitKey(0)
# fecha a janela.
cv2.destroyAllWindows()
Desafio 2¶
Vamos melhorar um pouco esse color picker...
Faça um script que ao clicar sobre a imagem, aparece a intensidade do pixel em RGB e abre uma nova janela (100x100) com essa cor.
# Implemente a solução aqui.....
Projeto 2¶
Vamos implementar um código que desenha um circulo na imagem conforme o mouse anda pela tela. (tipo Paint-Brush)
import cv2
import numpy as np
# Carrega uma imagem
# Neste caso estamos criando uma imagem RGB preta de tamanho 480x640
img = np.zeros((480, 640, 3), dtype="uint8")
# Exibe a imagem
cv2.imshow('image', img)
# Função de callback, quando ocorre um evento do mouse, essa função é chamada
def mouse_click(event, x, y, flags, param):
# Se foi movimento do mouse
if event == cv2.EVENT_MOUSEMOVE:
# Realiza função...
cv2.circle(img, (x,y), 20,(0,255,0), -1)
cv2.imshow('image', img)
# Seta a função de callback que será chamada
# Evento 'image', função callback mouse_click
cv2.setMouseCallback('image', mouse_click)
cv2.waitKey(0)
# fecha a janela.
cv2.destroyAllWindows()
Desafio 3¶
Ficou legal, mas ainda esta bem "zoado"...
Melhore este código, altere o código para desenhar um circulo na imagem se o botão esquerdo estiver pressionado, quando solta o botão para de desenhar.
Implemente tambem a função que limpa a tela quando o botão direto é pressionado.
# Implemente a solução aqui.....
Muito legal mas... pouco util até o momento. Vamos desenvolver aplicações mais interessantes.
Projeto 3¶
Vamos fazer um código que marca dois pontos na tela com o botão esquerdo e traça uma reta. Quando clica com o direito zera.
import cv2
import numpy as np
# Carrega uma imagem
# Neste caso estamos criando uma imagem RGB preta de tamanho 480x640
img = np.zeros((480, 640, 3), dtype="uint8")
# Exibe a imagem
cv2.imshow('image', img)
# Cria duas variaveis globais
clicks = 0 # conta a quantidade de clicks dada
coordinates = [] # salva as coordenadas de cada click
# Função de callback, quando ocorre um evento do mouse, essa função é chamada
def mouse_click(event, x, y, flags, param):
global clicks, coordinates, image
# Se foi movimento do mouse
if clicks < 2:
if event == cv2.EVENT_LBUTTONDBLCLK:
clicks += 1
coordinates.append([x, y])
cv2.circle(img, (x,y), 2,(0,255,0), -1)
cv2.imshow('image', img)
print(clicks, coordinates)
# Se foi o botão esquerdo do mouse
else:
if event == cv2.EVENT_RBUTTONDOWN:
img[:,:,] = 0
img[:,:,1] = 0
img[:,:,2] = 0
clicks = 0
coordinates = []
cv2.imshow('image', img)
else:
start_point = tuple(coordinates[0])
end_point = tuple(coordinates[1])
print(start_point,end_point)
cv2.line(img, start_point, end_point, (0,255,0), 2)
cv2.imshow('image', img)
# Seta a função de callback que será chamada
# Evento 'image', função callback mouse_click
cv2.setMouseCallback('image', mouse_click)
cv2.waitKey(0)
# fecha a janela.
cv2.destroyAllWindows()
Desafio 4¶
A logica implementada acima não foi a mais otimizada... mas com base nele (ou não), faça um programa que calcula o angulo entre quais 3 pontos. O resultado deve ser exibido no tela.
Dicas:
cv2.putText() para escrever na tela.
calculo do angulo: Se não lembra de trigonometria, não tem problema! Da um google de como calcular o angulo entre 2 linhas ou entre 3 pontos. por exemplo: https://manivannan-ai.medium.com/find-the-angle-between-three-points-from-2d-using-python-348c513e2cd
# implemente sua solução aqui...........
Projeto 4¶
A seleção de um região de interesse nada mais é que a determinação de das coordenadas iniciais e finais do boundbox.
import cv2
import numpy as np
# Carrega uma imagem
# Neste caso estamos criando uma imagem RGB preta de tamanho 480x640
img = np.zeros((480, 640, 3), dtype="uint8")
# Exibe a imagem
cv2.imshow('image', img)
points = []
# Função de callback, quando ocorre um evento do mouse, essa função é chamada
def mouse_click(event, x, y, flags, param):
global points
if event == cv2.EVENT_LBUTTONDOWN:
points = [(x, y)]
elif event == cv2.EVENT_LBUTTONUP:
points.append((x, y))
p1 = tuple(points[0])
p2 = tuple(points[1])
cv2.rectangle(img, p1 , p2, (0, 255, 0), 3)
cv2.imshow('image', img)
# Seta a função de callback que será chamada
# Evento 'image', função callback mouse_click
cv2.setMouseCallback('image', mouse_click)
cv2.waitKey(0)
# fecha a janela.
cv2.destroyAllWindows()
2024-04-01 11:56:24.318 Python[30860:5062868] Warning: Window move completed without beginning
Desafio 5¶
Faça um script que o usuario define uma area de seleção. essa imagem é aberta em uma nova janela e se for pressionado a tecla "s" salva a imagem no diretorio.
Dicas:
cv2.imwrite() para salvar.
if key == ord('s') : dar uma lida na função cv2.waiKey() e ord().
# Implemente sua resposta.......