Instituto Politécnico Nacional
Unidad Profesional Interdisciplinaria en Ingenierías y Tecnologías Avanzadas
(UPIITA)
PROYECTO FINAL
Visión Artificial
Parcial III
Alumno:
Calderón López Armando Emiliano
Garduño Sergio Jardon
Profesor:
ENRIQUEZ GAYTAN JESUS
Grupo:
4MM8
INTRODUCCIÓN:
En el presente reporte se documenta el desarrollo y la implementación de un sistema de
detección de objetos en video mediante la biblioteca OpenCV en Python, con la capacidad
de controlar un LED en una placa Arduino R4 WiFi en función de la presencia del objeto
detectado. Este proyecto tiene como objetivo demostrar la integración entre el
procesamiento de imágenes y el control de hardware, aplicando técnicas de visión por
computadora y comunicación serial.
El sistema utiliza un archivo de video pregrabado como fuente de datos y una imagen de
referencia del objeto que se desea detectar. La detección se realiza mediante la técnica de
coincidencia de plantillas, una de las metodologías básicas y efectivas para el
reconocimiento de patrones en imágenes. A través de un umbral de confianza
predeterminado, se establece si el objeto ha sido detectado con suficiente precisión en cada
fotograma del video.
Para la interacción con el hardware, se implementa una comunicación serial entre Python y
la placa Arduino R4 WiFi utilizando la biblioteca pyserial. Dependiendo del resultado de la
detección, se envían señales a la placa Arduino para encender o apagar un LED,
demostrando la capacidad de respuesta en tiempo real del sistema.
MARCO TEÓRICO:
Coincidencia de Plantillas
La coincidencia de plantillas es una técnica básica en el procesamiento de imágenes que se
utiliza para encontrar partes de una imagen que coinciden con una plantilla predefinida. En
esta metodología, una pequeña imagen de referencia (la plantilla) se desplaza sobre la
imagen más grande y se calcula una medida de similitud en cada posición. Las posiciones
donde la similitud supera un umbral determinado indican la presencia del objeto de interés.
Esta técnica es sencilla y efectiva para la detección de objetos en entornos controlados.
Biblioteca OpenCV
OpenCV (Open Source Computer Vision Library) es una biblioteca de software libre para
la visión por computadora y el aprendizaje automático. OpenCV proporciona más de 2500
algoritmos optimizados para realizar tareas comunes de procesamiento de imágenes como
la detección de objetos, el reconocimiento facial y la segmentación de imágenes. Es una
herramienta poderosa y ampliamente utilizada tanto en investigación como en aplicaciones
comerciales.
Comunicación Serial y Arduino
La comunicación serial es un método de transmisión de datos entre un ordenador y un
dispositivo periférico, como una placa Arduino. Este tipo de comunicación se realiza bit a
bit, permitiendo una transferencia de datos eficiente y fiable. En este proyecto, la biblioteca
pyserial en Python se utiliza para enviar señales desde el ordenador a la placa Arduino, la
cual ejecuta acciones basadas en las instrucciones recibidas.
Arduino R4 WiFi
La placa Arduino R4 WiFi es una plataforma de desarrollo basada en microcontroladores
que permite la creación de proyectos electrónicos interactivos. Equipada con capacidades
de conectividad inalámbrica, la Arduino R4 WiFi facilita el control y monitoreo remoto de
dispositivos. En este proyecto, la placa se utiliza para controlar un LED en respuesta a las
señales recibidas a través de la comunicación serial desde un script en Python.
Filtro Gaussiano en Procesamiento de Imágenes
El filtro Gaussiano es una técnica fundamental en el procesamiento de imágenes que se
utiliza para suavizar y reducir el ruido en una imagen. Este filtro aplica una función
Gaussiana a cada píxel de la imagen, promediando los valores de los píxeles vecinos
ponderados por su distancia desde el centro. La principal ventaja del filtro Gaussiano radica
en su capacidad para preservar los bordes importantes mientras elimina el ruido de alta
frecuencia. Es especialmente útil antes de aplicar técnicas de detección y reconocimiento de
objetos, ya que mejora la robustez y la precisión de los algoritmos al reducir la interferencia
causada por el ruido aleatorio.
Convolución en Procesamiento de Imágenes
La convolución es una operación matemática fundamental en el procesamiento de
imágenes, utilizada para aplicar filtros y máscaras a una imagen. En el contexto del
procesamiento de imágenes, la convolución implica deslizar una ventana (kernel o máscara)
sobre la imagen y calcular la suma ponderada de los valores de píxeles bajo la ventana en
cada posición. Esta operación es crucial para aplicar filtros como el filtro Gaussiano, el
filtro de media, el filtro Sobel (para detección de bordes) y otros filtros personalizados. La
convolución es eficiente computacionalmente y esencial para muchas operaciones
avanzadas de procesamiento de imágenes, incluida la detección de características y la
mejora de la calidad de la imagen.
Desarrollo:
Importaciones: Importamos las bibliotecas necesarias: cv2 para OpenCV, numpy para
manipulaciones numéricas, serial para la comunicación serial con Arduino, y time para
funciones relacionadas con el tiempo.
Inicialización de Serial: Se establece la comunicación serial con Arduino en el puerto
COM3 a 9600 baudios con un tiempo de espera de 1 segundo (timeout=1, este valor es
modificable a gusto del usuario pero se coloca un valor bajo para que el programa no este
esperando tanto tiempo en la recepción de la señal y no se tengan tiempos muertos de esta
forma al no recibir pulso mejor se cierra el programa).
Video: Se carga el video desde el archivo 'Fin.mp4, importante la terminación en mp4 para
la compatibilidad al ejecutar en Python, para que lo logre leer y no marque error' utilizando
cv2.VideoCapture.
Objeto a Detectar: Se carga la imagen del objeto que se desea detectar desde el archivo
"sin.jpg" en escala de grises (al poner el 0 de una vez al subirla como segundo argumento
de cv2.imread).
Esta será la plantilla de la imagen deseada que se comparará con cada fotograma por lo que
esta imagen puede variar conforme las necesidades del usuario.
NOTA:
Importante tenerla en jpg para su adecuada lectura, así como todos los archivos de imagen,
video, código y serial deben estar en la misma carpeta para su adecuado funcionamiento.
Así como la instalación en el CDM del pyserial para la comunicación serial de Python con
Arduino
Bucle While: Se itera sobre cada fotograma del video mientras cap.isOpened() sea
verdadero. ret indica si se pudo leer correctamente el fotograma, y frame contiene el
fotograma actual.
cap.isOpened() es un método que verifica si la apertura del video fue exitosa y si el video
está listo para ser leído.
El bucle while continuará ejecutándose mientras cap.isOpened() sea verdadero, es decir,
mientras el video esté disponible y no se haya alcanzado el final.
cap.read() es un método de OpenCV que lee un fotograma del video.
Devuelve dos valores: ret y frame.
ret: Es un valor booleano que indica si se leyó correctamente el fotograma. Si se
leyó correctamente, ret será True; de lo contrario, será False, lo que indica que no
hay más fotogramas para leer (fin del video o error).
frame: Es el fotograma actual que se ha leído del video. Es una matriz de NumPy
que representa el fotograma en formato BGR (Blue-Green-Red) por defecto en
OpenCV.
if not ret: break:
Esta línea comprueba si ret es False, lo cual significa que no se pudo leer un fotograma
válido esto significa que si no se logró leer es porque ya nos e cuenta con más fotogramas y
el video termino.
Si ret es False, se rompe el bucle while, lo que indica que no hay más fotogramas para
procesar (fin del video o error de lectura).
Conversión a Escala de Grises: El fotograma se convierte a escala de grises utilizando
cv2.cvtColor de la variable from con el valor actualizado constante del bucle.
Filtro Gaussiano: Se aplica un filtro Gaussiano (cv2.GaussianBlur) con un kernel de
tamaño (5, 5) para suavizar la imagen y reducir el ruido. El tercer parámetro 0 especifica la
desviación estándar en ambas direcciones x e y.
El filtro Gaussiano es una técnica de procesamiento de imágenes que se utiliza para
suavizar las imágenes y reducir el ruido. Cuando se aplica un filtro Gaussiano a una
imagen, se reemplaza cada píxel por una combinación ponderada de sus vecinos de acuerdo
con una distribución Gaussiana (normal), para hacer un promedio de colores alrededor de
un pixel y lo cambios no sean tan bruscos.
El tamaño del kernel especifica el área sobre la cual se calcula la media ponderada. Un
kernel de tamaño (5, 5) significa que se considera un área de 5 píxeles en horizontal y 5
píxeles en vertical alrededor de cada píxel para calcular la media ponderada.
Cuando se aplica el filtro Gaussiano, se realiza una convolución entre la imagen original y
el kernel Gaussiano. el 5*5 es el tamaño el cuadro.
Detección de Plantilla: Se utiliza cv2.matchTemplate para buscar el objeto (objeto) en el
fotograma suavizado (frame_blurred). cv2.TM_CCOEFF_NORMED indica el método de
coincidencia.
En resumen, el método de correlación normalizada cruzada (CCOEFF_NORMED)
compara la similitud entre la plantilla y la región de búsqueda en la imagen. Devuelve una
imagen de flotación de un solo canal que indica la "coincidencia" entre la plantilla y la
región de la imagen. Valores más altos indican una mayor similitud.
Una imagen de e flotación es donde cada pixel es un valor flotante normalizado.
La normalización se lleva a cabo para que los valores estén en el rango [0, 1], donde 1
indica una coincidencia perfecta.
Rectángulo de Detección: Si se encuentra el objeto con suficiente confianza (umbral
0.375), este se seleccionó tras prueba y error, al ejecutar el código se colocó la
condicionante if del umbral para el mejor valor que genera una adecuada detección y no
muestra falsos en momentos donde no esta el objeto o identifica otros. se dibuja un
rectángulo rojo alrededor del objeto en el fotograma (frame). Se envía la señal '1' a Arduino
a través de la comunicación serial para encender un LED.
Sin Detección: Si no se detecta el objeto, se envía la señal '0' a Arduino para apagar el LED.
La línea de código _, _, _, max_loc = cv2.minMaxLoc(result) en Python utiliza la
función cv2.minMaxLoc() de OpenCV para encontrar los valores mínimo y máximo en una
matriz.
La función devuelve cuatro valores
min_val: El valor mínimo encontrado en la matriz.
max_val: El valor máximo encontrado en la matriz.
min_loc: La coordenada (x, y) del valor mínimo encontrado.
max_loc: La coordenada (x, y) del valor máximo encontrado.
Si bien los otros valores son importantes para este caso no se usan, por lo que se marcan
con el símbolo para indicar que no nos importan y no los devuelva o tome, que solo nos de
el valor de la localización máxima.
Entonces, max_loc contiene las coordenadas (x, y) del punto donde se encuentra la mejor
coincidencia en la imagen, es decir, la esquina superior izquierda del área donde se
encuentra la plantilla en la imagen original.
bottom_right es una tupla que representa las coordenadas del punto inferior derecho del
rectángulo que se dibujará alrededor del objeto detectado en el fotograma de video.
bottom_right = (top_left[0] + objeto.shape[1] - margin, top_left[1] + objeto.shape[0] -
margin)
top_left[0] + objeto.shape[1] - margin: Calcula la coordenada x del punto inferior derecho
sumando la coordenada x de top_left con el ancho del objeto (objeto.shape[1]) y restando el
margen.
top_left[1] + objeto.shape[0] - margin: Calcula la coordenada y del punto inferior derecho
sumando la coordenada y de top_left con la altura del objeto (objeto.shape[0]) y restando el
margen.
El margin es un valor entero que se decalra hasta arriba y sirve para modificar en el tamaño
del recuadro que se dibujara si es grande o pequeño, se puede modificar a gusto del usuario
y se puede modificar conforme la ejecución del código y la visualización par una mejor
asignación de tamaño y evitar que esté justo en los límites del objeto detectado.
En OpenCV, objeto.shape se refiere a un atributo de la matriz de la imagen objeto que
indica las dimensiones de la imagen. a forma (shape) de esta matriz proporciona
información sobre las dimensiones de la imagen y su estructura. Especifica el número de
filas, columnas y canales de la imagen.
Mostrar y Esperar Tecla: Se muestra el fotograma con el objeto resaltado y se espera
que se presione la tecla 'q' para salir del bucle, mostrando cada frame analizado tras
otro para generar la ilusión de video.
Liberación de Recursos: Se liberan los recursos del objeto de captura (cap) y se
cierran todas las ventanas abiertas.
CONEXIÓN SERIAL ARDUINO:
Serial.available() > 0: Verifica si hay datos disponibles para leer desde el puerto serial. Si
hay datos disponibles, Serial.available() devolverá un valor mayor que cero, dado que
pusimos en el if principal del de Python que si se reconoce se envíe un en el canal de
comunicación serial.
char data = Serial.read();: Lee el byte de datos recibidos desde el puerto serial y lo
almacena en la variable data.
if (data == '1') { ... } else if (data == '0') { ... }: Compara el valor de data con '1' y '0'. Si
recibe el carácter '1', enciende el LED (digitalWrite(LED_BUILTIN, HIGH);). Si recibe el
carácter '0', apaga el LED (digitalWrite(LED_BUILTIN, LOW);).
Este ciclo se repite continuamente mientras el Arduino está alimentado y ejecutando el
programa.
Conclusión
En este proyecto, hemos explorado cómo utilizar la visión por computadora y la
comunicación serial para crear un sistema capaz de detectar y rastrear objetos específicos
en un video en tiempo real, utilizando la biblioteca OpenCV en Python y Arduino. A través
del análisis de imágenes y la aplicación de técnicas como el filtrado Gaussiano para reducir
el ruido y la coincidencia de plantillas para la detección precisa del objeto, hemos logrado
resaltar y encuadrar automáticamente el objeto de interés en el video.
La integración con Arduino nos permitió extender la funcionalidad del sistema más allá de
la visualización en pantalla, controlando un LED conectado al Arduino en respuesta a la
detección del objeto. Esta interacción entre el análisis de imágenes y la actuación física a
través de Arduino ilustra cómo la combinación de hardware y software puede ser utilizada
para aplicaciones prácticas y creativas en diversas áreas, desde la automatización industrial
hasta la interacción humano-computadora.
En resumen, este proyecto no solo ha demostrado la viabilidad de sistemas integrados
basados en visión por computadora y Arduino, sino que también ha proporcionado una
plataforma para explorar y entender cómo estas tecnologías pueden trabajar en conjunto
para resolver problemas del mundo real de manera efectiva y eficiente.