VISION ARTIFICIAL OPENCV PYTHON
VISION ARTIFICIAL OPENCV PYTHON
En esta práctica, vamos a desarrollar un sistema de visión artificial utilizando la librería de visión artificial opencv con Python. El objetivo del útil que aquí se expone es el de reconocer forma y color de distintas formas geométricas, además de la lectura de códigos QR. A continuación se exponen los elementos que conforman el útil para seguidamente explicar su funcionamiento.
Elementos del útil
El útil esta formado por los siguientes elementos:
-Motor paso a paso bipolar: El motor paso a paso, será el que dote de movimiento al conveyor. En este caso se ha elegido un motor pap bipolar, ya que respecto al unipolar, es mas pequeño, tiene menos cables, es mas barato y tiene mas torque. Tiene una resolución de 200 pasos por vuelta, es decir, cada paso corresponde a 1.8º. Se alimenta a 12 voltios y su intensidad nominal es de 2.5 amperios.
-Conveyor: El conveyor esta formado por el motor paso a paso y por una guía sinfín con una base. Este conveyor introducirá las piezas en el área de visualización de la cámara para su reconocimiento.
-ESP 32: Con el microcontrolador ESP-32, nos conectaremos con el driver TMC2130 mediante SPI para gestionar sus distintos parámetros y para controlar el motor paso a paso.
-TMC2130: El TMC2130, es un controlador ultra silencioso para motores paso a paso que utiliza el protocolo SPI para establecer una comunicación maestro-esclavo con un microcontrolador (por ejemplo). Este driver, tiene una gran cantidad de funciones como el modo stealthChop que ofrece un funcionamiento silencioso de alta precisión. El TMC2130 es capaz de dividir los pasos del motor paso a paso (200 por vuelta) en micro pasos. La relación es de 1 a 256, es decir, es capaz de conseguir una precisión de 51200 pasos por vuelta, lo que supone un movimiento de 0.007º por paso. Puede controlar motores alimentados a tensiones de entre 4.75 y 46 voltios. La corriente de fase RMS es de 1.2A. Se puede regular la intensidad que se le entrega al motor de dos maneras: Mediante software o mediante un potenciómetro situado en la parte superior del driver.
En la imagen superior, se puede ver el pinout del TMC2130, los pines correspondientes al protocolo SPI son: SDO,CS,SCK y SDI. Con el pin DIR, controlaremos al dirección del motor. Con el pin EN, habilitaremos o deshabilitaremos el driver. En el lado opuesto encontramos los pines de alimentación del driver (VIO y GND), los pines a los que conectaremos el motor paso a paso (M1B, M1A...), y por último, los pines de alimentación del motor (Vm y GND), que como hemos dicho anteriormente, aguanta tensiones entre 4,75 y 46 voltios. Es recomendable colocar un condensador de 100uF en la entrada de tensión del motor.
-Cámara 1: Se va a utilizar una web cam para reconocimiento facial.
-Cámara 2: Se va a utilizar otra web cam para el reconocimiento de figuras.
-Micrófono: Se va a utilizar un micrófono para dar una orden de arranque al sistema.
-Altavoz: Se va a utilizar un altavoz para hacer saber al usuario que tipo de pieza se ha detectado
-Raspberry pi 4: Para desarrollar este proyecto, se ha utilizado una raspberry pi 4 ya que nos ofrece unas características muy similares a las de un ordenador con un tamaño y un coste reducidos.
-Sensores IR: Se han utilizado dos sensores de infrarrojos para detectar la presencia o la no presencia de la base del conveyor en ambos extremos del carril.
-Relé: Se va a utilizar un relé para controlar el funcionamiento del ESP-32 (y por tanto del TMC y del motor) mediante la raspberry. Este relé será accionado por un GPIO de la raspi cuando se indique programáticamente.
Funcionamiento
Una vez explicados los componentes que van a formar este útil, se puede explicar el funcionamiento del mismo.
Python
Máquina de estados finita (FSM)
La gran mayoría del código del útil, se va a escribir en Python, este código va a estar estructurado como una máquina de estados finita, a continuación se expone lo que es una máquina de estados finita.
Una máquina de estados es un modelo de comportamiento de un sistema con entradas y salidas en dónde las salidas no dependen únicamente de las entradas actuales, sino que dependen también de las entradas anteriores. Se llama máquina de estados finita debido a que tiene un número de estados finito.
En la imagen superior se muestra la estructura de la máquina de estados de este proyecto, los círculos titulados como Sn, corresponden a cada uno de los estados de la máquina. También dentro de estos círculos, podemos ver las acciones que se llevan a cabo en cada estado. Con flechas, se indican las transacciones de un estado a otro. Encima de estas flechas, podemos ver las condiciones que se han de cumplir para pasar de un estado a otro. Ya que no se distingue muy bien en la imagen, voy a exponer los estados de la máquina a continuación:
-S0 -> Iniciamos conveyor
-S1 -> Reconocimiento facial
-S2 -> Orden de puesta en marcha por voz
-S3 -> Detección de movimiento
-S4 -> Detección de QR
-S5 -> Detección de forma y color
Al iniciar la máquina, la base del conveyor se desplazará hasta su posición inicial,
una vez allí colocaremos la pieza a leer. Para poner en marcha la máquina, deberemos de pasar por un reconocimiento facial, si este nos reconoce, la máquina nos pedirá por medio de un altavoz que demos la orden de arranque que en este caso es "arranca", entonces se pondrá en marcha la base del conveyor(mediante el motor) hasta llegar al área de visualización de la segunda cámara donde se ha definido un ROI*. Si se detecta movimiento dentro del ROI, el conveyor se detiene, pasando la máquina a ejecutar la lectura de QR. Si no se detecta ningún código QR, se ejecutará el reconocimiento de forma y color de
la pieza. Una vez reconocida, se dirán sus características de forma y color por medio del altavoz**. En el caso de que no se detecte movimiento, la base del conveyor avanzará hasta el final donde activará un sensor IR que le hará volver a la posición de inicio.
*Un ROI, es un área de interés que se define dentro de una imagen
**Tanto si se lee un código QR como si de identifica una figura, el conveyor volverá a su posición inicial.
Código
El código correspondiente a esta máquina de estados, se divide en dos partes, una primera en la que se definen todas las funciones del programa, y una segunda que se puede decir que es la máquina de estados en sí, en esta segunda parte: Se crean los estados, se establecen las transiciones de un estado a otro, se llaman a las distintas funciones, etc. A continuación se expone la parte del código que contiene las funciones.
Funciones (estados) FSM
En primer lugar, se importan todas las librerías que se van a utilizar en la máquina de estados, estas librerías, solamente será necesario importarlas en el sketch que contiene las funciones de la máquina de estados.
Las librerías que se importan son para distintas aplicaciones, como la visión artificial, el reconocimiento facial, el reconocimiento de voz, el control de tiempos, el tratamiento de arrays, el control de los GPIO, salida de audio, o para el tratamiento de imágenes
Iniciamos conveyor |
Con esta función, iniciaremos el conveyor, es decir, si el conveyor no esta en su posición inicial, haremos que vaya a ella controlando su movimiento. En el momento en el que se detecte la presencia del conveyor en la posición inicial, saldremos de este estado, devolviendo como argumento de la función el valor de la variable salida (true).
Estado 1 - Reconocimiento facial
Para poder realizar el reconocimiento facial, es necesario que previamente hayamos guardado una foto de la persona que queramos reconocer en la misma carpeta que el programa. Esta foto debe ser lo mas clara posible, teniendo un buen contraste la persona con el fondo, debe ser una imagen de la cara. Es recomendable que la imagen se tome con la misma cámara con la que se va a realizar el reconocimiento, si la imagen es muy pesada, el reconocimiento se demorará.
Reconocimiento facial |
En el fragmento de código de la imagen superior, se carga la imagen personal y se extraen las características del rostro para su posterior comparación con la persona que está intentando acceder. También en este fragmento, se inicia la webcam, es decir, se abre la cámara.
Reconocimiento facial |
En el fragmento de código de la imagen superior, capturamos imágenes mediante la web cam, si esta imagen se ha tomado correctamente, pasaremos a modificar la imagen para hacer que el reconocimientos sea mas rápido y preciso, a continuación compararemos la imagen procesada con la imagen que tenemos almacenada, si ambos rostros coinciden, escucharemos un mensaje de voz que nos indique que nos ha reconocido.
Reconocimiento facial |
En el fragmento de código de la imagen superior, en las primeras líneas, podemos ver el caso de cuando no reconoce a la persona que está intentando acceder, en este caso, lanza un mensaje de voz por medio del altavoz que nos indica que no nos ha reconocido. El resto de código corresponde a distintas animaciones que se generan sobre la imagen como por ejemplo, un rectángulo verde alrededor de tu cara si te reconoce. Al final, podemos ver que la variable salida de pone en True y salimos, al hacer esto, vamos a salir del estado 2 al finalizar el código, es decir, cuando se devuelva el valor de la variable Salida.
Reconocimiento facial |
El fragmento de código de la imagen superior, muestra el resultado del reconocimiento en una ventana. Se establece también una condición. Cuando la variable nombre es igual a 'Soy yo :)', es decir, cuando tu rostro ha sido reconocido, cierra todas las ventanas que se habían abierto y sale del bucle, es entonces cuando cerramos también la web cam y se devuelve el valor de la variable Salida.
Estado 2 - Orden de puesta en marcha por voz
A continuación, se muestra el código correspondiente a la puesta en marcha mediante voz.
El fragmento de código de la imagen superior, es el correspondiente al estado de puesta en marcha por voz. Vamos a utilizar la librería pyttsx3 para, mediante el altavoz, dar instrucciones al usuario. Utilizando la librería speech recognition y sus funciones, vamos a poder introducir una orden por voz y convertirla a texto. Una vez damos la orden, se compara lo que hemos dicho con la palabra clave 'arranca', si ambos string coinciden, pondremos la variable Salida en nivel alto (true) y saldremos del bucle, devolviendo el valor de la variable Salida (true) y saliendo así del estado dos.
Estado 3 - Detección de movimiento
El código que se expone a continuación es el correspondiente a la detección de movimiento.
Detección de movimiento |
El fragmento de código que se muestra en la imagen superior, es el correspondiente a la declaración de variables y la configuración de los GPIO que se vana a utilizar. También se crea el objeto cap, que va a contener lo que capture la función cv2.videocapture(). Las dos ultimas líneas forman parte del procesado de imagen, la captura (en color), se pasa a una escala de grises y se guarda en la variable gris_prev, después se le aplica un filtro gaussiano para suavizar la imagen. Estas capturas, se utilizarán para compararlas con las que la cámara va tomando, para de este modo, cuando la imagen anterior sea diferente a la imagen actual, sabremos que hay movimiento.
Detección de movimiento |
Estado 4 - Lectura de QR
A continuación se muestra el código correspondiente a la parte de lectura de códigos QR.
Lectura de QR |
En este fragmento de código mostrado en la imagen superior, se utiliza la librería web browser para, en caso de detectar un código QR, abrir la página web que contiene en una ventana nueva. Después de abrir el navegador, muestra animaciones sobre la imagen como un rectángulo alrededor del QR. Al igual que en el estado anterior, hay dos salidas posibles, que son: Hay código QR, no hay código QR. En el caso de que si haya, la variable salida, tomará un valor de 2, y en el caso de que no haya código, la variable salida tomará un valor de 1. Como el sistema puede tardar unos segundos en detectar el QR, se ha puesto un contador para no producir una salida accidental del estado .
Estado 5 - Detección de forma y color
A continuación, se muestra l aparte del código correspondiente a la identificación de forma y color de figuras geométricas.
Detección de forma y color |
Las primeras líneas del código que se muestra en la imagen anterior son las correspondientes a las máscaras definidas para el color verde y el color azul. Después de haber definido las máscaras, se unen como una sola mediante la función cv2.add, de este modo se podrá detectar cualquiera de los tres colores. A continuación, utilizando la función cv2.bitwise_and()* restamos la imagen actual captada por la cámara con las tres máscaras al mismo tiempo, obteniendo así una imagen con el fondo negro y una forma geométrica con el color detectado.
Aplicamos un ROI para delimitar el área en el que se encuentra la figura y lo pasamos a una escala de grises. Aplicamos también un filtro kernel para eliminar el ruido de la imagen.
*La función bitwise_and() muestra los pixeles que son diferentes en una imagen y en otra.
Comparación con lógica digital |
Detección de forma y color |
Finalmente, a través del altavoz se indica la forma y el color de la figura identificada. Las dos últimas líneas lo que hacen es, que en el caso de que se quiera ejecutar este código no se pueda, es decir, este código solamente se ha desarrollado para que las funciones que en el se definen, puedan ser utilizadas por el sketch de la máquina de estados.
Sketch máquina de estados
A continuación se va a exponer el código de la maquina de estados finita.
Máquina de estados |
El fragmento de código que se muestra en la imagen superior, es el correspondiente al estado uno de la máquina de estados, es decir, al inicio del conveyor.
En primer lugar, mostramos en que estado se encuentra la máquina, a continuación llamamos a la función uno_dos, que si recordamos, se encuentra en el sketch 'estados_fsm' y es la correspondiente al movimiento del conveyor hacia su posición de origen. El parámetro que devuelve esta función, lo guardamos en la variable salida y va a ser el valor de esta variable el que determine si se permanece en el estado o si se sale del mismo y se transiciona la siguiente. En caso de que la variable salida sea True, transicionamos al estado dos mediante la función UNO_DOS() de la máquina de estados.
Máquina de estados |
El siguiente estado que se va a exponer es el estado cuatro ya que este es diferente a los anteriores. Lo que hace diferente a este estado, es que de el se puede ir a dos estados diferentes según se cumplan unas condiciones u otras (como se vio en el sketch 'estados_fsm'). Transicionar de un estado a otro no depende de si la variable salida esta en True o en False, sino que depende del número que devuelva la variable salida. En este caso si la variable salida devuelve un 1, transicionaremos al estado cinco, mientras que si la variable salida devuelve un 2, transicionaremos al estado uno.
No se van a exponer mas estados ya que se repite la misma programación que en estos dos.
Programación ESP-32
A continuación se expone el código desarrollado en el ESP 32 para el control del motor paso a paso. Con este programa vamos a controlar los pasos del motor y a configurar distintos parámetros del TMC2130 desde el microcontrolador ESP32. Toda esta programación se ha llevado a cabo en el entorno de programación de Arduino.
Programación ESP-32 |
En la parte de Setup del código de la imagen superior, se limita la corriente que se le entrega al motor (con la función rms_current()), se habilita el modo ultra silencioso (con la función stealthChop()) o se configuran los micro pasos con la función microsteps(). En el loop simplemente se acciona el motor de manera indefinida a una velocidad constante determinada por el stepDelay. El motor no va a estar funcionando constantemente, ya que mediante el pin enable del TMC controlaremos el funcionamiento.
MONTAJE
A continuación se mostrarán unas imágenes del montaje del útil:
ENLACES DE DESCARGA
Comentarios
Publicar un comentario