lunes, 19 de noviembre de 2012

Reporte Final

Aportes:
  • Pre procesamiento para detección de caracteres
    • Binarización
    • Escalamiento
    • Segmentación de Caracteres
    • PCA para datos de entrada
  • Perceptrón simple con aprendizaje y clasificación en N capas.
  • Red Neuronal Multicapa(XOR)
  • Red Neuronal con Datos Reales (Error en aprendizaje)
Repositorio(Usuario - Synnick):
Reporte

Pre procesamiento (pre_caracter.py en el repositorio)

En el reporte de medio curso se trabajo en lo que era el pre procesamiento de las imágenes de automóviles para obtener datos de ellas y encontrar las placas. Lamentablemente ni yo ni mis compañeros pudimos encontrar la manera de obtener datos de la misma, por lo cual optamos por obtener los datos directamente de una placa ya encontrada.

Ahora mi aportación fue, teniendo una imágen de una placa, cortar su tamaño a una zona relevante (en donde viene la placa) y a partir de esa zona, localizar los caracteres y segmentarlos en diferentes imágenes del mismo tamaño.

Para realizar ésto utilicé una combinación de OpenCV y la librería PIL de Python. Los pasos son así:

Primero el programa toma una imágen de una placa, como la siguiente:


A esta imágen se le realiza una serie de preprocesamientos antes de buscar las letras, el primero es convertirlo a escala de grises:


Después le aplicamos un smooth para eliminar algunos ruidos aleatorios que pudiera tener:


Lo siguiente es binarizar la imágen, aplicando un threshold:



Para terminar el preprocesamiento de la placa completa, adelgazamos la imágen, haciendo los caracteres mucho más delgados y deshaciendonos de muchas partes innecesarias. Con todo esto queda así:


Esta es la imágen que se segmentará, pero antes se cortara para dejar solo la placa incluida.
El algoritmo para cortar la imágen es sencillo. Se colocan dos lineas imaginarias en el centro de la imágen, extendiendose a todo el largo de la misma, pero de solo 1 pixel de largo. Estas líneas después se recorreran, una hacia abajo y otra hacia arriba, deteniendose hasta que no haga contacto con ningun espacio en blanco(normalmente letras). 

La posición en la que se detengan las líneas será la parte de la imágen que cortaremos para obtener solo los caracteres de la placa. El resultado es el siguiente:


Ahora por último localizamos los caracteres dentro de la imágen. Para encontrar primero los caracteres, se utiliza OpenCV y findContours para encontrar todos los contornos de las letras y objetos visibles en la imágen. Esto por sí nos arroja más contornos que los que necesitamos, ya que detecta algunos caracteres en dos contornos separadamente además de completo, por lo que tenemos que agregar un filtro, conservando solo los contornos que sean similares al tamaño del alto de la imágen. Todo esto se ve a continuación:

Sin filtro:

Con filtro:


Ya localizados los caracteres en la imágen, debemos ordenarlos de izquierda a derecha(el orden de la matrícula de un automóvil), esto es sencillo y basta con ordenar una lista con las posiciones de los rectángulos de menor a mayor (de x menor a x mayor).
Con eso podemos proceder a cortarlos en diferentes imágenes, además normalizandolas a un mismo tamaño(30x70):


De cada imágen se obtendrían datos de entradas utilizando PCA.

PCA (pca.py en el repositorio)


El PCA(Principal Component Analysis) es es una técnica utilizada para reducir la dimensionalidad de un conjunto de datos. Intuitivamente la técnica sirve para hallar las causas de la variabilidad de un conjunto de datos y ordenarlas por importancia.

En nuestro caso se utiliza para obtener datos de entrada para la neurona de las imágenes de los caracteres previamente segmentados.

Para implementar PCA, hacemos uso de una librería llamada MDP (Modular kit for Data Processing), un framework con muchas funciones para implementar procesamiento de datos. Entonces podemos obtener datos de entrenamiento de, por ejemplo, los 7 caracteres anteriores corriendo el programa.


Estos datos son buenos porque, como se puede observar con los últimos dos datos (obtenidos de las dos imágenes con 8), el valor es prácticamente el mismo, pero con un diferente exponente, esto porque hay pequeñas variaciones entre los dos 8.

Pero como necesitamos 7 entradas para la neurona para poder separar entre todos los caracteres (es necesario 7 bits para poder separar todas las clases diferentes), usando la misma función del PCA solicitando que nos de vectores de 7 de largo. Esto nos produce un nuevo problema ya que aunque nos genera vectores de 7 de largo, genera 30 vectores por lo cual para arreglarlo simplemente aplicamos la transpuesta, y obtenemos 7 vectores de largo 30.

 Estos vectores los sumamos por separado, y obtenemos  7 valores por imágen.


Estos se escriben en un archivo para que la neurona pueda usarlos.

Neurona - Perceptrón Simple ( neurona.py [versión anterior] )

Debido a que no contabamos con una neurona que pudiera aprender, me di a la tarea de leer acerca de las neuronas para poder implementar alguna que fuera útil para el proyecto. Dicho eso mi primer paso fue realizar un perceptrón simple que pudiera clasificar en varias clases como fuera necesario. El resultado fue exitoso, logré implementar el perceptrón simple, siendo capaz de clasificar datos en rangos de números aprendiendo rápidamente para dejar de tener errores alrededor de las 400s iteraciones. El funcionamiento de la neurona con 400 iteraciones y separando en 5 clases:

                                                                      ...


Mi idea para la aplicación de esta neurona en el proyecto era que, siendo capaz de clasificar en n clases, podríamos obtener diferentes datos de entrada de cada caracter con pocas variaciones entre los mismos, siendo entonces la red neuronal capaz de determinar cuál letra es con los datos de entrada, y entrenandose a sí mismo a modo que los recibe. 

Red Neuronal con datos reales ( neurona.py más nueva)

Para que la neurona que hicé tuviera una aplicación hacia el proyecto la adapté hacia los datos generados por el PCA. Lo que hace es simplemente solicitar el número de iteraciones y neuronas a usar (7 neuronas para los caracteres de la placa) y un archivo con las muestras de entrada que se usarán.

Del archivo recoge las muestras y hace las operaciones, entrenando cada neurona cuando se equivoca individualmente. El problema es que solo algunas clases parecen entrenarse y funcionar correctamente, mientras las demás siguen equivocandose sin aprender. 

1 comentario:

  1. LOL, según el repositorio de Champy, trabajaron hace un mes y dentro de los últimos 24 horas :D Mayor consistencia y continuidad hubiera sido deseable. Van 19 por tu código.

    El reporte está bastante bien, van los 10 pts por ello.

    ResponderEliminar