Procesamiento de Imágenes Python



Procesamiento de Imágenes Python

En esta ocasión escribiré un poco sobre lo que eh aprendido al llevar a cabo los conocimientos estudiados de procesamiento de imágenes (lo que llevo por el momento) y aplicarlo a uno de mis lenguajes de programación favoritos, Python.

Para ello se utilizara Python y el modulo de OpenCV para procesar la imagen, y el objetivo será encontrar el histograma de la imagen.

Histograma:
Un histograma es una representación gráfica de una variable en forma de barras, donde la superficie de cada barra es proporcional a la frecuencia de los valores representados. En el eje vertical se representan las frecuencias, y en el eje horizontal los valores de las variables, normalmente señalando las marcas de clase, es decir, la mitad del intervalo en el que están agrupados los datos.
En términos matemáticos, puede ser definida como una función inyectiva (o mapeo) que acumula (cuenta) las observaciones que pertenecen a cada subintervalo de una partición.

En una imagen un histograma es una grafica representativa del conteo de las ocurrencias de intensidades de luz encontradas en cada pixel de la misma.
Es de este concepto que surge la idea del resultado, siguiendo los siguientes pasos.

  1.  Leer la imagen de alguna locación del disco.
  2. Adecuarla a un arreglo que podamos manejar de manera correcta y conocer su dominio (yo utilizo el 0-255).
  3. Prepara un arreglo del tamaño del dominio de la imagen, con un tipo de dato lo suficientemente grande para contar cada ocurrencia de valor de intensidad.
  4. Recorrer la imagen para encontrar las ocurrencias, contarlas y almacenarlas en el arreglo resultante.
  5. Mostrar el resultado en forma de gráfica.


Primer intento:

(Para los que sepan de Python, una disculpa por el desorden de las cosas xP)

import cv
import numpy
image=cv.LoadImage('image.png', cv.CV_LOAD_IMAGE_COLOR)
mat=cv.GetMat(image)

res = ((numpy.zeros(256)),(numpy.zeros(256)),(numpy.zeros(256)))
resImg = cv.CreateImage((512,600),cv.IPL_DEPTH_8U,3)

for i in range(0,mat.rows-1):
for j in range(0, mat.cols-1):
res[0][mat[i,j][0]] += 1
res[1][mat[i,j][1]] += 1
res[2][mat[i,j][2]] += 1

maxx = (max(res[0]),max(res[1]),max(res[2]))
for k in range(0,3):
for i in range(0,256):
cv.Rectangle(resImg, (i*2,200 * (k+1)), (i*2+1, 200*(k+1)-
int(res[k][i]*200/int(maxx[k]))), cv.RGB(i,255-i,0))

cv.ShowImage('Histograma',resImg)
cv.ShowImage('Imagen',image)
cv.WaitKey(0)

Este código cumple básicamente con cada uno de los puntos y devuelve una imagen dibujada en ejecución con la grafica del histograma, lamentablemente el performance es muy bajo,  ya que Python es muy tardado al manejar estructuras de barrido de arreglos, como el que se utiliza para el cálculo del histograma. (En mi netbook tardo unos 13 segundo aproximados en una imagen de 500 x 300 a color)
Por lo que al no quedar satisfecho con el resultado indague un poco sobre el porqué de la lentitud del programa y algunas soluciones, un texto que me fue de gran ayuda fue: http://www.python.org/doc/essays/list2str.html donde se estudia un caso práctico de manejo de este tipo de patrones en Python.
Después de algunos intentos llegue al siguiente resultado:



import cv
import numpy

def cont(x):
mt=Mat[Act]
return mt.count(x)

image=cv.LoadImage('image.png', cv.CV_LOAD_IMAGE_COLOR)
b = cv.CreateImage(cv.GetSize(image), image.depth, 1)
g = cv.CloneImage(b)
r = cv.CloneImage(b)
cv.Split(image, b, g, r, None)
b=b.tostring()
g=g.tostring()
r=r.tostring()
Mat = (r,g,b)

resImg = cv.CreateImage((512,600),cv.IPL_DEPTH_8U,3)
res = (range(256),range(256),range(256))

Act=0
cht = map(chr, range(256))
for k in range(0,3):
Act=k
r = map(cont,cht)
maxx=max(r)
for i in range(0,256):
cv.Rectangle(resImg, (i*2,200 * (k+1)), (i*2+1, 200*(k+1)- int(r[i]*200/maxx)),cv.RGB(i,255-i,0))

cv.ShowImage('Histograma',resImg)
cv.ShowImage('Imagen',image)
cv.WaitKey(0)

Este código resulta ser mucho más eficiente ya que en la misma computadora le tomo menos de un segundo realizar por completo el script devolviendo el mismo resultado que el anterior, para ello hice uso de algunas de las recomendación de performance en Python, como el utilizar los arreglos en una función y manejarlos como variables locales, utilizar maps y funciones definidas en los tipos de datos, como el count en los arreglos.



Para la próxima entrada del blog publicare el tema de operaciones de pixel en el procesamiento de imágenes.

0 comentarios: