Login Form

En este artículo se describe un pequeño proyecto que, si bien está lejos de resultar algo útil en la vida real, sirve como un buen ejemplo introductorio del uso del Procesamiento de Imágenes Digitales en un sistema de Reconocimiento de Patrones.

 

El proyecto consiste en poder discriminar si un objeto dado, contenido en una imagen digital, es un plumón o no.
La idea de este artículo no es hacer algo complejo que asombre sino todo lo contrario, intentar, a manera de introducción, hacer algo práctico de la manera más sencilla posible por lo que,  tanto el ambiente como la herramienta utilizada para la implementación, serán seleccionados de manera que faciliten este objetivo.

 

Teniendo en mente lo anterior, se utilizará MATLAB con el Image Processing ToolBox de manera que nos podamos olvidar de los detalles de implementación para el manejo de las imágenes y de los distintos algoritmos que se usarán y, en su lugar, nos podamos enfocar precisamente en utilizar y probar distintas opciones de los mismos. Por supuesto que al momento de la redacción de este artículo, ya se tiene un algoritmo seleccionado e implementado por lo que sólo se describirá el algoritmo final.

 

En cuanto al ambiente, nos olvidaremos de las dificultades que enfrentan ciertas aplicaciones de Visión Computacional y simplificaremos enormemente el esfuerzo requerido para la segmentación y detección de la ubicación del objeto de interés en la imagen controlando el fondo y la iluminación. Este tipo de decisiones o conocimiento previo acerca del entorno se tienen en ambientes completamente controlados como por ejemplo, en aplicaciones para la inspección de calidad de piezas en la industria donde se sabe exactamente cuál es el fondo, la ubicación exacta de la pieza y se puede controlar la iluminación.

 

 

Proceso General

 

El algoritmo, como el típico sistema de R.P. que es, tiene los siguientes pasos:

1.- Adquisición de la Imagen: El objetivo aquí es obtener una imagen, en este caso a través de una cámara web y almacenarla en memoria para después usarla.

2.- Preprocesamiento: Una vez que tenemos la imagen, necesitamos, de algún modo, ubicar dónde se encuentra el objeto a ser analizado y separarlo del resto de la imagen.

3.- Extracción de las Características: Creación del patrón a ser analizado.

4.- Clasificación: Evaluación del patrón.

 

Preparación del Entorno

 

Para la fácil segmentación de la imagen, podemos utilizar un fondo de un color contrastante a los objetos que se intentan clasificar. Para este ejemplo, utilicé dos cartulinas de color verde fosforecente, una puesta sobre la pared y la otra sobre el suelo.

La imagen la vamos a adquirir a través de una cámara web la cuál podemos colocar al inicio de la cartulina que se encuentra en el suelo:

 

Entorno

A continuación iremos describiendo cada etapa, mostrando y explicando a su vez, el código utilizado.

 

Adquisición de la Imagen

 

En esta etapa, simplemente tomamos una imagen utilizando la cámara web y la guardamos en memoria. El código utilizado es el siguiente:

Captura de la imagen

La siguiente es una imagen de ejemplo adquirida mediante el código mostrado arriba:

 

Ejemplo de Imagen Capturada

 

Preprocesamiento

 

Lo que nos interesa en este punto, es la localización del objeto en la imagen para poder separarlo del fondo y que sea más fácil la extracción de las características. Si trabajaramos con la imagen original sin un preprocesamiento, sería más dificil poder medir el objeto.

Para esto, binarizamos la imagen, es decir, a partir de la imagen en RGB, creamos una imagen con tan solo valores de pixeles de 1 y 0, siendo 1 los pixeles pertenecientes al fondo y 0 los pertenecientes al objeto.

Para lograr eso, recurrimos a nuestro conocimiento previo del ambiente controlado, donde sabemos que el fondo es verde. Lo que debemos hacer entonces, es mandar el verde a blanco y el resto de los colores a negro.

Esto lo realizamos creando una nueva imagen con tan sólo los valores de verde de la imagen original:

 

Extracción de la imagen en verdes

Ahora bien, sabemos que los pixeles pertenecientes al fondo, tendrán valores más altos en esta nueva matriz que aquellos pertenecientes al objeto, pero, por si llegara a haber algún valor alto en verde en el objeto (por ejemplo algúna zona en blanco), los separamos aún más restándole al valor de verde, alguna fracción de su respectivo valor en azul y en rojo:

justGreen =  g - r/3.5 - b/3.5

 

¿Por qué hacemos esto?; por que sabemos que los pixeles del fondo tendrán valores altos de verde y relativamente bajos de azul y rojo por lo que al restárselos, permanecerán más o menos en los valores que tenían. Por el contrario, los pixeles pertenecientes al objeto que puedan tener valores altos de verde, es muy probable que también tengan valores altos de azul o de rojo por lo que al restarlos, se encontrarán muy por debajo de los valores del fondo.

 

La imagen resultante se ve de la siguiente manera:

Imagen en verdes

Como se puede ver, el objeto se oscurece bastante con respecto al fondo.

Una vez que tenemos esta imagen, podemos proceder a binarizarla. En realidad existen diversos métodos para encontrar un umbral de manera automática pero, ya que nuestro ambiente es altamente controlado, podemos seleccionar un umbral cualquiera encontrado experimentalmente, ya que sabemos que en las siguientes tomas, el ambiente no cambiará por lo que nuestro umbral seguirá funcionando. Por si acaso, podemos aplicar una operación morfológica de erosión para quitar ruido que pudiera quedar en el fondo. Esto se debe a algunas pruebas en las que pequeños puntos en el fondo quedaron como si fueran parte del objeto, en vez de parte del fondo:

Binarización y Erosión

La imagen binarizada se ve de la siguiente forma:

 

Imagen Binaria

Una vez que tenemos la imagen binaria, podemos localizar las coordenadas de las cuatro esquinas donde se encuentra el objeto para posteriormente, recortarlo de la imagen RGB:

Extracción del objeto

 

 

Objeto

 

Extracción de Características

 

Con el objeto aislado, de la imagen RGB, obtenemos sus características para la formación del vector que representa el patrón del objeto. Aquí se pueden utilizar las características que se consideren relevantes.

Para el propósito de este ejercicio, a manera de ejemplo, consideramos la entropía de la imagen, la media del valor de los pixeles en RGB, la desviación estandar, la proporción entre anchura y altura y el alto y ancho en centímetros (tomando un factor alfa de conversión obtenido experimentalmente).

Con el siguiente código extraemos las características mencionadas:

 

Características

 

Clasificación

 

Para la clasificación, utilizaremos el perceptrón simple ya explicado en este artículo. De hecho,  se utiliza la misma clase de JAVA proporcionada para el entrenamiento. La función de activación, para las pruebas, la podemos codificar directamente en Matlab.

Pues bien, la tarea ahora es conseguir la muestra de entrenamiento. Para esto, podemos tomar varias fotos y aplicar el procedimiento descrito anteriomente para la extracción de sus diversas características. En realidad, para el entrenamiento, tomé fotos de 6 plumones y de 6 objetos que no son plumones y, con el código ya expuesto, formé los 12 patrones con los que entrené el perceptrón. Como los valores entre distintas características son muy dispares, hay que normalizarlos. El procedimiento más sencillo es simplemente la división de los valores de cada característica entre su valor máximo, por ejemplo, suponiendo que tuvieramos para la característica de la altura los siguientes valores de 4 patrones: 20, 21, 10, 7. Cada uno de esos valores los deberíamos dividir entre 21 quedando así: 0.952,1, 0.476, 0.35.

Ese mismo procedimiento se debe aplicar para todas las características y, una vez formados los patrones, podemos entrenar el clasificador, en este caso el perceptrón, para la obtención de los pesos a utilizarse.

 

Al final del artículo dejo un zip con un archivo en excel con los patrones originales y normalizados, el perceptrón en java que se utilizó y el código de Matlab completo junto con algunas fotos que se tomaron por si quieren experimentar con el código. Lo único que hay que hacer es, en vez de obtener la imagen de la cámara, leerla del sistema de archivos descomentando la línea de imread y comentando las líneas que utilizan la cámara web.

 

Bueno, pues retomando, una vez obtenido los pesos a utilizar, podemos codificar la función de activación en matlab:

Función de Activación en Matlab

Por último, como los pesos se obtuvieron con patrones normalizados, es importante, antes de llamar a la función de activación, "normalizar" los valores que se obtengan del objeto que se esté evaluando:

 

Llamada al clasificador

 

Pues espero que este artículo haya sido de utilidad y dejo aquí el código fuente del proyecto.

 

Add comment


Security code
Refresh

contacts Contactanos

 

bugs Reportar bugs

about Acerca de www.tecnohobby.net

Go to top