Convolución Discreta 2D
Para poder aplicar una máscara de convolución a una matriz de los pixeles de una imagen, primero decidí programar dicha operación para una matriz simple, comprobando que el funcionamiento fuera el correcto. El ejemplo que utilicé fue:
La idea es centrarse en un pixel determinado, y a partir de ese "empalmar" la máscara sobre el mismo, y realizar una suma de las multiplicaciones de cada par de celdas que se empalman, incluyendo la cual está centrada.
De no existir algún valor al empalmarse(por ejemplo en la imagen anterior, debido a que es una esquina no existen valores para multiplicar el -1, -2, -1, 0 y 1) se toma como 0 la operación y se suman solamente los existentes.
El resultado de dicha suma se guarda en una tercera matriz, es importante recordar esto ya que estamos haciendo estos cálculos con los valores originales, no actualizando la matriz original.
La matriz resultante debe ser la siguiente:
El código que hace lo anterior es el siguiente:
Aplicación de máscara para detección de bordes
Ya con la correcta implementación de la convolución lo siguiente es usarla en una imagen, aplicando una máscara. Para esto solo se carga una imagen en una matriz, se convierte en escala de grises y después se le aplica alguna mascara a elección a cada elemento de la matriz de pixeles. Para mejorar los resultados, es decir, que no aparezcan líneas discontinuas visibles, ayuda usar un filtro promedio después de convertir los pixeles a escala de grises.
A continuación mostraré los resultados de aplicar diferentes máscaras a 3 pares de imagenes.
Imagen Original Imagen Nueva
Imagen Original Imagen Nueva
Aplicación de máscara para detección de bordes
Ya con la correcta implementación de la convolución lo siguiente es usarla en una imagen, aplicando una máscara. Para esto solo se carga una imagen en una matriz, se convierte en escala de grises y después se le aplica alguna mascara a elección a cada elemento de la matriz de pixeles. Para mejorar los resultados, es decir, que no aparezcan líneas discontinuas visibles, ayuda usar un filtro promedio después de convertir los pixeles a escala de grises.
A continuación mostraré los resultados de aplicar diferentes máscaras a 3 pares de imagenes.
Máscara
Imagen Original Imagen Nueva
Conclusión: La máscara marca correctamente los bordes en imagenes con poco ruido como comics. Pero en imagenes mas complejas los bordes son poco definidos y aparece mucha interferencia.
Máscara (Sobel para líneas horizontales)
Imagen Original Imagen Nueva
Conclusión: La máscara se comporta de buena manera para líneas horizontales, marcándolas de buena forma, las líneas verticales podrían ser mejores.
Máscara (Sobel para líneas verticales)
Conclusión: Como la anterior, pero ahora la máscara encuentra de forma excelente las líneas verticales, ignorando algunas partes de las horizontales, por lo cual sería deseable combinarlas.
Máscara (Sobel vertical + horizontal + Prewitt 45°)
(Nota: Se suman las matrices para combinar los resultados)
Imagen Original Imagen Nueva
Conclusión: La detección de bordes se comporta excelente en imagenes con dibujos y comics, encontrando casi la totalidad de bordes, cortándose en algunas partes. La imagen mas compleja, siendo la de en medio cuenta con mucho ruido por lo cual la detección falla en algunas partes.
Código de la aplicación de máscaras:
Tiempos de Ejecución
Imagen 1: 53.3538572232 segundos
Imagen 2: 105.186025143 segundos
Imagen 3: 71.6054358482 segundos
Tiempos horribles, sí. Veré la manera de mejorarlos en un futuro cercano.
*FIXED*
El problema al parecer era el uso de una matriz de numpy para la máscara. Al cambiarla por listas de python los resultados mejoraron considerablemente, siendo los siguientes:
Imagen 1: 4.64621206919
Imagen 2: 9.65786719322
Imagen 3: 6.70177864234
Ahora los tiempos son bastante aceptables, tardando tan solo 4.6 segundos en la imagen mas pequeña(468x375), 6.7 segundos en la imagen mediana(364x600) y 9.6 segundos en la mas grande(713x500).
Muy bien. Al usar paréntesis, se les pone un espacio antes. 5 pts.
ResponderEliminar