0% encontró este documento útil (0 votos)
60 vistas9 páginas

Estudio de Codigo

Este documento describe cómo implementar la detección de gestos mediante el análisis de imágenes de la mano y la detección de contornos. Utiliza OpenCV, NumPy y RPi.GPIO para procesar video en vivo, identificar el número de dedos levantados y controlar LED en consecuencia.

Cargado por

Max Ga
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
60 vistas9 páginas

Estudio de Codigo

Este documento describe cómo implementar la detección de gestos mediante el análisis de imágenes de la mano y la detección de contornos. Utiliza OpenCV, NumPy y RPi.GPIO para procesar video en vivo, identificar el número de dedos levantados y controlar LED en consecuencia.

Cargado por

Max Ga
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 9

#-*- coding: utf-8 -*-

"""importamos librerias o modulos de python:


->numpy
->cv2 ->opencv
->math
->RPi.GPIO ->GPIO Raspberry pi3
"""
import numpy as np
import cv2
import math
import RPi.GPIO as GPIO
#----------------------------

#sistema de numeración son los números de BCM.número de canal


va a qué pin en la placa RPi.
GPIO.setmode(GPIO.BCM)

#desactivar estas advertencias


GPIO.setwarnings(False)

#lista de pines a utilizar segun la enumeración BCM


led = [13,19,21,20]

"""Debe configurar cada canal que esté utilizando como entrada o


salida.
canal como entrada:
>>GPIO.setup(canal, GPIO.IN)

canal como salida :


>>GPIO.setup(canal, GPIO.OUT)
"""
GPIO.setup(led, GPIO.OUT)

#capturar un video o entrada de una camara


capture = cv2.VideoCapture(0)

#verificar si está inicializado o no por el método cap.isOpened


()
while capture.isOpened():

try:

# capturamos frame o cuaadro 640x480 por defecto


ret, frame = capture.read()

#dibujaremos un rectángulo verde en frame


cv2.rectangle(frame,(50,50),(450,450),(0,255,0),0)
#delimitarmos la frame para hacer un mejor analisis
crop_image = frame[50:450,50:450]
# Desenfocamos crop_image usando un filtro gaussiano
blur = cv2.GaussianBlur(crop_image, (3,3), 0)

"""convertirmos crop_image de un espacio de color a otro,


como BGR Gray, BGR HSV, etc.
convertiomos BGR --> HSV

Para HSV, el rango de tono es [0,179], el rango de


saturación es [0,255]
y el rango de valores es [0,255].

Diferentes softwares usan diferentes escalas. Entonces, si


comparas los valores
de OpenCV con ellos, necesitas normalizar estos rangos.

"""
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)

"""definir el rango de color de la piel en HSV


Crea una imagen binaria con los colores de piel en blanco
y el resto es negro
"""
mask = cv2.inRange(hsv, np.array([2,0,0]),
np.array([40,255,255]))

# Kernel para transformación morfológica


#Devuelve una nueva matriz de forma y tipo dados, rellenos
con unos.
kernel = np.ones((5,5))

#Aplicar transformaciones morfológicas para filtrar el


ruido de fondo
#aumenta la región blanca en la imagen o el tamaño del
objeto
dilation = cv2.dilate(mask, kernel, iterations = 1)

#erosiona los lÃmites del objeto en primer plano


erosion = cv2.erode(dilation, kernel, iterations = 1)

# Apply Gaussian Blur and Threshold


#disminuye la región blanca en la imagen o el tamaño del
objeto

#Desenfocamos erodion usando un filtro gaussiano


filtered = cv2.GaussianBlur(erosion, (3,3), 0)
#se le asigna un valor (puede ser blanco = 0), de lo
contrario(puede ser negro =1)
ret,thresh = cv2.threshold(filtered, 127, 255, 0)

# Mostrar imagen de umbral


#----->cv2.imshow("Threshold", thresh)
# encontrarmos los contornos contornos de la imagen umbral
contours, hierarchy = cv2.findContours(thresh,
cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE )

# Encuentramos el contorno con el área máxima


contours_dos = max(contours, key = lambda x:
cv2.contourArea(x))

#encontramos la circunferencia circunscrita de un objeto


contours
(x,y),radius = cv2.minEnclosingCircle(contours_dos)
center = (int(x),int(y))
radius = int(radius)
cv2.circle(crop_image,center,radius,(0,0,255),2)

#compruebamos una curva de defectos de convexidad y la


corregimos
hull = cv2.convexHull(contours_dos)

#compruebamos una curva de defectos de convexidad y la


corregimos
hull = cv2.convexHull(contours_dos, returnPoints=False)
#Encuentra los defectos de convexidad de un contorno.
defects = cv2.convexityDefects(contours_dos,hull)

# Use cosine rule to find angle of the far point from the
start and end point i.e. the convex points (the finger
# tips) for all defects
count_defects = 0
#efectos debido a los dedos
for i in range(defects.shape[0]):
s,e,f,d = defects[i,0]
start = tuple(contours_dos[s][0])
end = tuple(contours_dos[e][0])
far = tuple(contours_dos[f][0])

cv2.line(crop_image,far,start,[255,0,0],2)
cv2.line(crop_image,far,end,[255,0,0],2)

#encontrar la longitud de todos los lados del


triángulo
a = math.sqrt((end[0] - start[0])**2 + (end[1] -
start[1])**2)
b = math.sqrt((far[0] - start[0])**2 + (far[1] -
start[1])**2)
c = math.sqrt((end[0] - far[0])**2 + (end[1] -
far[1])**2)

#Fórmula de herón para hallar el area de los


tinagulos.
s = (a+b+c)/2
ar = math.sqrt(s*(s-a)*(s-b)*(s-c))

#distancia entre el punto y el defecto de convexidad


d=(2*ar)/a

angle = (math.acos((b**2 + c**2 -


a**2)/(2*b*c))*180)/3.14

# iignorar los ángulos > 90 y distancia < 30


if angle <=90 and d>50 :
count_defects += 1
#dibujamos circuplo en los angulos > 90
cv2.circle(crop_image,far,4,[255,0,255],-1)

#dibujarmos lÃneas alrededor de la mano


cv2.line(crop_image,start,end,[0,236,255],2)

# imprime los gestos correspondientes que están en sus


rangos
if count_defects == 0:
cv2.putText(frame,"UNO", (50,45),
cv2.FONT_HERSHEY_SIMPLEX, 2,(0,0,255), 3)
GPIO.output(led, False)

elif count_defects == 1:
cv2.putText(frame,"DOS", (50,45),
cv2.FONT_HERSHEY_SIMPLEX, 2,(0,255,170), 3)
GPIO.output(led, False)
GPIO.output(13, True)
GPIO.output(19, False)
GPIO.output(21, True)
GPIO.output(20, False)
elif count_defects == 2:
cv2.putText(frame, "TRES", (50,45),
cv2.FONT_HERSHEY_SIMPLEX, 2,(251,255,0), 3)
GPIO.output(led, False)
GPIO.output(13, False)
GPIO.output(19, True)
GPIO.output(21, False)
GPIO.output(20, True)
elif count_defects == 3:
cv2.putText(frame,"CUATRO", (50,45),
cv2.FONT_HERSHEY_SIMPLEX, 2,(0,236,255), 3, 2)
GPIO.output(led, False)
GPIO.output(13, False)
GPIO.output(19, True)
elif count_defects == 4:
cv2.putText(frame,"CINCO", (50,45),
cv2.FONT_HERSHEY_SIMPLEX, 2,(255,0,147), 3, 2)
GPIO.output(led, False)
GPIO.output(21, True)
GPIO.output(20, False)
else:
GPIO.output(led, False)
except:
pass

# Mostrar imágenes requeridas

#----->cv2.imshow("Gesture", frame)

# Cierre la cámara si se presiona 'q'


if cv2.waitKey(1) == ord('q'):
GPIO.output(led, False)
break

GPIO.output(led, False)
#Limpiamos todos los pines de salida
GPIO.cleanup()
#liberar la captura
capture.release()
#La función destroyAllWindows destruye todas las ventanas HighGUI
abiertas.
cv2.destroyAllWindows()
NumPy

NumPy es unPaquete fundamental que se puede utilizar para calcular


científicamente con Python. Es una librería matricial para el álgebra
lineal. NumPy también se puede utilizar como un contenedor multidimensional
eficiente de datos genéricos. Se pueden definir y usar tipos de datos
arbitrarios. NumPy es una extensión del lenguaje de programación
Python. Agrega soporte para matrices y matrices multidimensionales grandes,
junto con una gran biblioteca de funciones matemáticas de alto nivel que se
pueden usar para operar en estas matrices

OpenSource Computer Vision ¶


OpenSource Computer Vision, más comúnmente conocido como OpenCV, es
un software de procesamiento y manipulación de imágenes más avanzado
que PIL. Se ha implementado en varios idiomas y es ampliamente utilizado.

Primero hablemos de lo que es BCM. BCM significa canal Broadcom


SOC. Básicamente, estos números de pin siguen el sistema de numeración de nivel
inferior definido por el cerebro del chip Broadcom de Raspberry Pi. Déjame
explicarte que con la ayuda de un ejemplo,

Vea el siguiente diagrama de pin de Rpi a continuación:

Ahora, si quiero referirme a los pines con los números representados en círculos (es
decir, 1, 2, 3, ...) entonces los estaría refiriendo con el método GPIO.BOARD .
Pero si quiero referir los pines con los números representados en los rectángulos
alrededor de los pines (es decir, GPIO 21, GPIO 25, ...) entonces en ese caso
me referiría al método GPIO.BCM .

math- Funciones matemáticas


Este módulo está siempre disponible. Proporciona acceso a las funciones
matemáticas definidas por el estándar C.
Estas funciones no pueden usarse con números complejos; use las funciones del
mismo nombre del cmathmódulo si necesita soporte para números complejos. La
distinción entre las funciones que admiten números complejos y las que no lo hacen
se hace ya que la mayoría de los usuarios no quieren aprender tantas matemáticas
como sea necesario para entender los números complejos. Recibir una excepción
en lugar de un resultado complejo permite una detección más temprana del número
complejo inesperado utilizado como parámetro, de modo que el programador pueda
determinar cómo y por qué se generó en primer lugar.

Las siguientes funciones son proporcionadas por este módulo. Excepto cuando se
indique explícitamente lo contrario, todos los valores de retorno son flotantes.

Aunque sea en rojo no es un error, sino que te avisa de que intentas redefinir como salidas
pines que ya estaban definidos previamente y te informa que puedes desactivar etas
advertencias con el comando:

gpio.setwarnings(False)

Capturar video desde la cámara¶


A menudo, tenemos que capturar la transmisión en vivo con la cámara. OpenCV
proporciona una interfaz muy simple para esto. Capturemos un video de la cámara
(estoy usando la cámara web incorporada de mi computadora portátil), la convertimos
en video en escala de grises y la mostramos. Sólo una tarea sencilla para empezar.

Para capturar un video, necesita crear un objeto VideoCapture . Su argumento puede


ser el índice del dispositivo o el nombre de un archivo de video. El índice del dispositivo
es solo el número para especificar qué cámara. Normalmente se conectará una cámara
(como en mi caso). Así que simplemente paso 0 (o -1). Puede seleccionar la segunda
cámara pasando 1 y así sucesivamente. Después de eso, puedes capturar fotograma a
fotograma. Pero al final, no te olvides de liberar la captura.

También podría gustarte