En artículos anteriores de Visión Artificial hemos visto cómo manejar y procesar imágenes con OpenCV. También hemos visto la dificultad de pasar de los cálculos en OpenCV a acciones del robot, ya que teníamos que guardar los datos en un fichero, descargarlos al NXT, y procesarlos con RobotC u otro entorno. Sin embargo es posible procesar imágenes con LabVIEW, lo que es de gran utilidad ya que desde LabVIEW podemos además manejar al NXT directamente. Esto nos puede servir para procesar las imágenes que tome una cámara en tiempo real, lo que tiene muchas aplicaciones prácticas.
Lectura y Escritura de una Imagen:
En LabVIEW podemos tanto abrir como escribir imágenes. Las funciones que necesitamos se encuentran en Programming → Graphics & Sound → Graphics Formats como podéis ver en la siguiente imagen:
Las funciones para lectura de imágenes reciben como parametro de entrada la dirección de la imagen, y devuelven un cluster con los datos de la imagen en caso de que la lectura haya resultado exitosa, o un error por la salida de error en caso de que haya habido algún fallo a la hora de abrir la imagen. Podéis ver todas las entradas y salidas de las funciones gracias a la ayuda contextual:
Las funciones de escritura reciben como entrada la misma estructura de datos con los datos de la imagen y la dirección donde queremos guardar la nueva imagen, y devuelven si ha habido algún fallo o no a la hora de escribir. La ayuda contextual es la siguiente:
A la hora de tratar con la imagen que acabamos de leer es necesario poder acceder a los distintos componentes del cluster de información de la imagen, especialmente al que que tiene la información de los píxeles. Para ello necesitaremos usar la función unbundle cluster que podéis encontrar en Programming → Cluster, Class & Variant :
Nos interesa especialmente el array de una dimensión, que contiene toda la información de los píxeles de la imagen. Recorriendo dicho array podremos saber de que color es cada píxel, y poder operar con la imagen para crear una nueva imagen modificada. Igualmente necesitaremos hacer uso de la función bundle cluster situada también en Programming → Cluster, Class & Variant para juntar la información de la imagen y escribirla en el disco duro (mirar la imagen anterior).
¿Cómo manejar la imagen?:
Dentro de nuestro ordenador una imagen es un conjunto de datos que podemos leer y modificar a nuestro antojo, en el caso de LabVIEW estos datos están agrupados en un cluster que podemos dividir usando la función unbundle vista anteriormente. Como ya sabréis, el tamaño de las imágenes se mide en píxeles, que son pequeños puntos que se definen por su brillo y color. Por ejemplo si cambiamos la resolución de nuestra pantalla veremos la misma imagen (de 600×400 píxeles) más pequeña o más grande.
Los píxeles pueden tomar valores distintos según el tipo de imagen. Las imágenes en blanco y negro son las más básicas, pudiendo tomar sus píxeles valores entre 0 (completamente negro) y 255 (completamente blanco). Sin embargo las imágenes de color contienen tres canales de colores distintos (los famosos RGB (R : rojo, G : verde, B : Azul). Cada canal puede tomar un valor entre 0 y 255, por ejemplo un R = 255, G = 0, y B = 0 será un píxel completamente rojo. Si los tres valores son 255 el píxel será blanco, y si los tres valen 0 el píxel será negro. Existe además el sistema HSB (Hue, Saturation, Brightness (Matiz, Saturación, Luminosidad)) también llamado HSV, con el que también se puede crear cualquier color, y que tiene transformación directa a su representación en el sistema RGB mediante la siguiente formula:
Sea MAX el valor máximo de los componentes (R, G, B), y MIN el valor mínimo de esos mismo valores, los componentes del espacio HSV se pueden calcular como:
Hay incluso televisiones que actualmente incluyen el amarillo entre sus canales de color, por lo que incrementa mucho el número de colores posibles.
Toda está información de los colores la tenemos guardada en LabVIEW en el array de una dimensión que forma parte de los datos del cluster de la imagen. El tamaño de dicho array es esactamente altura x anchura x canales. Para recorrer una imagen en LabVIEW se va de izquierda a derecha, y de arriba a abajo. Teniendo en cuenta además que los canales están ordenados en RGB (rojo, verde y azul), si quisiésemos acceder al valor verde del píxel número 40 de la fila 24 tendríamos que acceder al dato: anchura_fila*23 + numero_canales*39 + 1, donde anchura_fila será la anchura de la imagen multiplicada por el número de canales. Está es la única forma de recorrer imágenes, y se implementa con bucles generalmente.
Programa de prueba:
En este programa de prueba vamos a recorrer una imagen entera y mostrar en el panel frontal cuál es el píxel actual en cada momento, y que valores RGB tiene. Se implementa de la siguiente manera:
Como veis se ha usado un bucle anidado que nos permite recorrer fácilmente la imagen. Ademas se ha añadido un objeto que nos muestra la imagen en el panel frontal, y un control para elegir que imagen es la que queremos recorrer. Tenemos además un pequeño retardo de 100 ms entre píxel y píxel para que podamos ver como va avanzando y recorriendo la imagen. El búcle while donde está metida la lectura de la imagen no termina hasta que la lectura haya sido correcta, lo que nos garantiza que el programa no dará fallos de ejecución por intentar recorrer una imagen que no existe. Como podéis ver la salida de error de la lectura de imágenes también es un cluster de datos, por lo que necesitaremos utilizar otro unbundle para sacar el valor booleano que nos dirá si ha habido error o no de lectura.
El panel frontal en ejecución tiene el siguiente aspecto:
Se pueden ver el valor que van tomando todas las variables. Para comprobar si esos valores son verdaderos necesitamos un programa como el Photoshop, donde podemos abrir esa misma imagen y ver si es cierto que a los mismos píxeles les corresponden los mismos valores RGB.
Espero que el artículo sea de vuestro agrado y os animéis con LabVIEW, que es una herramienta potente y con muchas posibilidades.