Operaciones Pixel xP


OperacionesDe Pixel
Sonaquellas operaciones sobre imágenes en donde solo es tomado en cuenta el valordel pixel en cuestión de la imagen.
 f[I(x,y) ]→I^' (x,y)


Sila función es independiente de la posición se llama homogénea. Como por ejemploveremos algunas de las operaciones pixel citadas a continuación:

Cambios decontraste

Aplicación decurvas de iluminación.

Inversión ocomplemento de una imagen.

La segmentaciónpor umbral.

Corrección gamade una imagen.

Transformaciónde color de una imagen.


1.- Cambio de Valor de la intensidad.

Contraste ehiluminación.
Contrastees la relación existente entre los diferentes valores de intensidad presentes.La iluminación se relaciona se relaciona con la forma en que los valores deintensidad están distribuidos
Eloperador genérico F( … ) que se utiliza para modificar el contraste o lailuminación en una imagen puede ser definido como:

I^' (x,y)=f(x,y)=c.I(x,y)+b

Donde c es la variable de cambio para el contraste y b parael brillo.
for i inrange(0,mat.rows-1):
    for j in range(0, mat.cols-1):
        r = mat[i,j] * c + b


Delimitación deresultados por operaciones pixel.
Estetipo de operaciones pueden generar valores de pixel excedentes al valor límitedefinido en la imagen. Por ejemplo si usamos enteros de 8 bits (byte) seriacualquier valor mayor a 255 por lo que hay que delimitar los resultados a estemáximo, al igual con los valores menores de 0 como se muestra:
if (r >0):
            if (r<256):
                mat[i,j] = int(r)
            else:
                mat[i,j] = 255
        else:
            mat[i,j] = 0

Complemento de unaimagen.
Esla inversión de la imagen, se realiza al restar el valor de la posición almáximo valor posible del dominio para cada pixel.

f(p)=Pmax-p

Segmentación porumbral.
Esuna operación en la que los pixeles son divididos en 2 clases, dependiendo deun umbral (“threshold”) predefinido Pth:

Pth = p0 si P<Pth o p1 si p>=Pth

Esto se utiliza para la adecuar binariamente una imagen p0=0y6 p1=1.


2.- Histograma y Operaciones Pixel
Enalgunos casos los efectos de las operaciones pixel pueden ser fácilmentedetectables a través del histograma. Por ejemplo, un aumento de luz desplaza elhistograma completo a la derecha.
Puederesultar de alguna operación 2 valores de intensidad distintas resulten en unvalor igual, con eso decimos que la imagen se encuentra vinculado a una pérdidade dinámica y en la información de la imagen.

Adaptación automática del contraste.
Elobjetivo de esta adaptación de contraste es que los pixeles de una imagen seancombinados de tal manera que el intervalo completo de valores de la intensidadsea cubierto.
Paraesto tomamos el valor más oscuro y lo consideramos el valor más pequeño, aligual con el más alto y realizamos interpolación con todos los demás valores.

Fac=(p-Plow).(Pmax-Pmin)/(Phigh-Plow)

Ecualización lineal del Histograma.
Equilibrarel histograma significa cambiar mediante operaciones pixel la imagen de talforma que muestre un histograma en la mejor medida distribuido a lo largo detodos los niveles de entendida.
Paraesta operación se requiere utilizar el histograma acumulativo, con la intenciónde volver a este similar a una ecuación linear.

mk= 1/Size . ∑_(j=1)^k n(j)

Matlab:
I = imread('imagen1.bmp');
nk1 = imhist(I);
rk1 = nk1./numel(I);
suma = cumsum(rk1);
rk2 = suma.*256;
bar(rk2, nk1, 1);


Adaptación del histograma porespecificación.
Estatécnica hace posible transformar una imagen de tal forma que su histograma separezca a una distribución o histograma especifico.

Probabilidades e histogramas de frecuencia.
Lasuma de todos los valores de un histograma h(i) para una imagen I de tamaño M,N es igual a la multiplicación de MN.
Elcorrespondiente histograma normalizado queda definido como

N(i)=h(i)/sum(h)   para 0≤i<k

Elcual puede ser interpretado como su distribución de posibilidad.
Lacontraparte del Histograma Acumulativo H(i) es la función de DistribuciónDiscreta:

hN(i)=∑ h(i)/sum(h) = ∑ hN(i)   para 0≤i<k

Através de esta formulación estática es posible modelar a la imagen como unproceso aleatorio.


3.- CorrecciónGamma
Lacorrección gamma es una operación de pixel que permite compensar las diferentescaracterísticas mediante la utilización de un espacio general de intensidades.
Función Gamma

b=fr(a)=a^r
Donder es mayor que 0, el parámetro r es llamado factor gamma.

0 comentarios:

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:

Consejos para la Depuración

Comentario Personal:
Cuando uno estudia y aprende a programar en cualquier lenguaje sin ayuda de un material debidamente estructurado y sin ayuda de algún mentor, es normal que en ocasiones se utilice un código extenso o poco limpio debido a la falta de conocimiento de técnicas o metodologías bien estudiadas y desarrolladas.
Pero es importante el buscar y desarrollar sistemas limpios, que optimicen el código y den un resultado mas limpio y profesional.
Al leer este libro de C++ eh descubierto muchos aciertos y errores que mi camino de desarrollador me han dejado, y muchas técnicas y soluciones simples que de haber conocido antes, habrían resuelto muchos de los problemas a los cuales eh enfrentado con anterioridad de manera mucho mas sencilla y cómoda, como lo es el tema de esta ocasión.
Por lo cual invito a cualquier persona que se encuentre en una situación similar, que el programar haya surgido de un gusto nato, y no contase con algún estudio debido del tema, a leer materiales técnicos y de gran valor que den un sentido profesional y bases fuertes para este hobby xP... Digo yo puee xP

Consejos para la depuración.

En ocasiones no contaremos con un buen depurador de nuestro lado que haga al programa trasparente y poder descubrir errores de manera fácil y rápida. O puede que se trabaje con sistemas embebidos (empotrados) donde no hay depuradores y exista una retroalimentación muy limitada, como un led o pantalla lcd de 1 o 2 lineas.

A continuación se explicaran algunas buenas sugerencias para esto.

Banderas para la depuración.

En ocasiones tendremos que agregar código que nos ayudara en el proceso de depuración, y luego este código sera un estorbo (en memoria o en lectura) y sera borrado, después surgirá de nuevo algún error y volverá  teniendo esto en un ciclo vicioso y estorboso en tiempo en agregar y quitar este código.
Una solución a esto es utilizar algunas banderas que permitan separa el código de depuración y activarlo o desactivarlo, y para esto tenemos 2 opciones.


  • Banderas de pre-procesador.
Usando el pre-procesador para definir (#define) una o mas banderas de depuración puede así separa el código de depuración con las sentencias #ifdef y #endif. Condicionando el código de depuración a una bandera de pre-procesador.
Cuando crea que la depuración ah terminado utilice #undef con esa bandera y el código quedara eliminado automáticamente (con esto reducirá el tamaño y sobrecarga del ejecutable).
"Las banderas de pre-procesador tradicionalmente se distinguen de las variables porque se escriben todas en mayúscula".

#define DEBUG
.......
#ifdef DEBUG
//Codigo de depuración....
....
#endif //end of debugging

  • Banderas en Tiempo Real.


En ocasiones es mas conveniente utilizar banderas en tiempo de ejecución que puedan modificarse sin la necesidad de re-compilar el código (esto es esencialmente importante en sistemas muy grandes, que nos permitirán ahorrar todo el proceso de compilación).
Para esto se utilizan banderas booleanas.

bool debug = false;
....
if(debug){
     //codigo ....
}

En ocasiones también puede ser conveniente que la bandera de depuración se active como un argumento de inicio de la aplicación (--debung=on), permitiendo así activar los programas en este modo cuando sean requeridos.


Salutaciones Finales xP
Esta misma técnica del pre-procesador puede ser muy útil (y es utilizada) para la habilitación y negación de bloques de código en la compilación, permitiendo activar módulos de sistemas muy grandes, o dejarlos fuera para ciertas empaquetados o para la prueba en partes del mismo :)

0 comentarios: