miércoles, 28 de enero de 2009

HISTOGRAMA DE IMÁGENES A COLOR

El histograma de una imagen a color RGB consiste en tres gráficas
siendo cada una el histograma de cada color primario:



Calcular el histograma de una imagen, es simplemente contar el número de apariciones de cada uno de los posibles niveles de gris presentes en la misma. Si la imagen es en color, es posible extraer tres histogramas, cada uno de ellos correspondiente a un color primario. En nuestro caso, decidimos obtener previamente una imagen de luminancia sobre la que calculamos su histograma, paso previo que también se requiere para una posible y posterior ecualización de la imagen con idea de mejorar su contraste. En este último caso, también se obtienen dos matrices diferencia de color. Una vez ecualizada la matriz de luminancia, pasamos del formato YIQ anterior al RGB original. En nuestra aplicación, existe un procedimiento que se encarga de calcular y dibujar el histograma de las imágenes y se ejecuta cada vez que hacemos click en el botón correspondiente.

HISTOGRAMA (TRATAMIENTO IMAGEN A COLOR)

En el caso de la imagen en color, aparecen tres histogramas, es por esto que el tratamiento de imágenes en color se complica por la aparición de nuevos componentes. Al elaborar el histograma, la función del algoritmo es separar el color correspondiente a cada pixel en sus componentes RGB (rojo, verde y azul).

Aunque el resultado puede no ser satisfactorio, porque las componentes de color de cada pixel son modificados independientemente, y el matiz de color de cada pixel puede cambiar.

Este proceso de tratamiento de imágenes se lo conoce como Proceso de ecualización.


Histograma para Imagenes a Color

Histograma de una Imagen a Color.
El histograma de una imagen contiene la información de la probabilidad de aparición de las distintas tonalidades de color que se pueden dar.
Con un Histograma de una imagen se pueden corregir fallas en la distribución de los colores de la imagen. Es muy importante en la corrección de fallas en los tonos.
En el caso de una imagen en color, no podemos hablar de un único histograma que caracterice a la imagen sino de tres histogramas, uno para cada color (RGB).
Al elaborar el histograma, el algoritmo debe separar el color correspondiente a cada pixel en sus componentes RGB (rojo, verde y azul).
Ejemplo de una imagen cualquiera con sus respectivos Histogramas


clase que obtiene el color promedio de una imagen a través de su histograma de color.

- Es un sistema de votación, tenemos una matriz tridimensional
histograma[r][g][b] inicializada a ceros.
- Recorremos cada pixel de la imagen y obtenemos su componente r, g y b.
- Con esas 3 componentes incrementaremos el valor de la casilla
correspondiente: histograma[r][g][b]++
- Finalmente, la casilla que mayor valor tenga será la del color dominante

Puntualizaciones:
- Para sacar el color con error cero, habría que crear una matriz
histograma[256][256][256], que consumiría demasiada memoria y tiempo
para rellenarla.
- Lo que se hace para reducir tiempo y memoria es discretizar el
histograma a, por ejemplo, [64][64][64], de forma que el pixel con
valores de rgb 32,64,128 en lugar de votar por la casilla [32][64][128],
votaría por la casilla [8][16][32], ya que hemos dividido el espacio de
colores entre 4. Esto significa que el color 33,65,129 votaría por la
misma casilla que el color anterior, pero este error es admisible ya que
a simple vista no podremos diferenciar un color de otro.
- Varios ejemplos de color promedio dependiendo del número de niveles en
el que hayamos dividido el histograma:
- [20][20][20] -> rgb = 26 64 13
- [40][40][40] -> rgb = 45 51 32
- [50][50][50] -> rgb = 46 51 36
- [80][80][80] -> rgb = 48 51 35
- [150][150][150] -> rgb = 49 53 38
- [180][180][180] -> rgb = 50 53 38
- Como se puede observar, a mayor número de niveles más preciso es el
algoritmo, pero mucho más tiempo y memoria consume. Con 50 niveles ya
obtenemos un color aceptable que no dista mucho del promedio real, y a
simple vista es inapreciable.

A continuación la clase sin optimizaciones para que sea más legible:


public static function getColorPromedioSinOptimizar(bitmap:BitmapData,
niveles:Number):Number {
var histograma:Array = [];
for (var i:Number=0; i histograma[i] = [];
for (var j:Number=0; j histograma[i][j] = [];
for (var k:Number=0; k histograma[i][j][k] = 0;
}
}
}

var rango:Number = 256 / niveles;
var colorPromedio:Number = 0;
var mayor:Number = 0;

var w:Number = bitmap.width;
var h:Number = bitmap.height;
var totalPixeles:Number = w*h;
var valorVotacion:Number = 1 / totalPixeles;
for (var i:Number=0; i for (var j:Number=0; j var color:Number = bitmap.getPixel(i, j);
var r:Number = (color >> 16) & 0xFF;
var g:Number = (color >> 8) & 0xFF;
var b:Number = color & 0xFF;
r = Math.floor(r / rango);
g = Math.floor(g / rango);
b = Math.floor(b / rango);
histograma[r][g][b] += valorVotacion;
if (histograma[r][g][b] > mayor) {
mayor = histograma[r][g][b];
colorPromedio = color;
}
}
}
return colorPromedio;
}


Y a continuación la clase optimizada, que es menos legible pero funciona
casi el doble de rápido:

public static function getColorPromedio(bitmap:BitmapData,
niveles:Number):Number {
var histo:Array = [];
for (var i:Number=niveles-1; i>=0; i--) {
histo[i] = [];
var histo1:Array = histo[i];
for (var j:Number=niveles-1; j>=0; j--) {
histo1[j] = [];
var histo2:Array = histo1[j];
for (var k:Number=niveles-1; k>=0; k--) {
histo2[k] = 0;
}
}
}

var rango:Number = 256 / niveles;
var rangos:Array = [];
var f:Function = Math.floor;
for (var i:Number=0; i<256; i++) {
rangos[i] = f(i / rango);
}

var w:Number = bitmap.width;
var h:Number = bitmap.height;
var valorVotacion:Number = 1 / (w*h);

var colorPromedio:Number = 0;
var mayor:Number = 0;

for (var i:Number=0; i for (var j:Number=0; j var color:Number = bitmap.getPixel(i, j);
var r:Number = rangos[(color >> 16) & 0xFF];
var g:Number = rangos[(color >> 8) & 0xFF];
var b:Number = rangos[(color & 0xFF)];
histo[r][g][b] += valorVotacion;
if (histo[r][g][b] > mayor) {
mayor = histo[r][g][b];
colorPromedio = color;
}
}
}
return colorPromedio;
}


Es un método estático que se pude incluir en vuestras clases ColorUtils o
similares. El primer parámetro es un objeto BitmapData con la imagen y
el segundo es el número de niveles en el que vamos a dividir el histograma.

Un ejemplo de uso podría ser este:

//imagen es un MovieClip con una imagen dentro en su coordenada (0,0)
var bmp:BitmapData = new BitmapData(imagen._width, imagen._height);
bmp.draw(imagen);

var colorPromedio:Number = ColorUtil.getColorPromedio(bmp, 50);

//resultado es un MovieClip con un cuadrado negro
//lo coloreo para ver el color promedio de la imagen
var c:Color = new Color(timeline.resultado);
c.setRGB(colorPromedio);


Para imágenes más pequeñas o menos niveles, evidentemente menos tiempo.

Histograma para Imagen a color

Para una imagen a color o imagen codificada en RGB se necesitan de varios histogramas
- Un histograma que representa la distribución de luminancia y tres histogramas que representan la distribución de los valores de los componentes

rojo (con una longitud de onda de 700,0 nm)verde (con una longitud de onda de 546,1 nm)azul (con una longitud de onda de 435,8 nm)

Para la obtencion del Histograma a color se debe realizar lo siguiente:

El algoritmo debe separar el color correspondiente a cada pixel en sus componentes RGB (rojo, verde y azul).
Para el procesado de Histogramas existe dos tecnicas para el procesado
ecualización y especificación de histograma

La ecualización del histograma consiste, en una expansión del histograma de la imagen, dotando al mismo de mayor linealidad y haciendo que éste ocupe el ancho del espectro de tonalidades
En si el objetivo de la ecualización del histograma es armonizar la distribución del nivel de luminosidad de la imagen, de tal manera que cada uno de los niveles del histograma tienda hacia contener el mismo número de píxeles.
Esta operación se propone aumentar los matices de la imagen.

martes, 27 de enero de 2009

Histograma a Color

Segun Wikipedia "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 una imagen en escala de grises el rango de colores seria de 256 (de 0 a 255), en cambio en una imagen a color RGB el histograma consistiría en gráficas de cada color primario es decir una para RED, una para GREEN y finalmente para BLUE que combinadas o sopbreponiendolas tendríamos una imagen con las frecuencias de los tres colores primarios.

HISTOGRAMA (IMPLEMENTACION EN JAVA)

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

public class Histograma implements PlugInFilter
{
ImagePlus Iplus;

public int setup(String arg, ImagePlus Iplus) {
this.Iplus = Iplus;
return DOES_8G + NO_CHANGES ;
}

public void run(ImageProcessor ip)
{

int [] K = new int [256];
int d = ip.getWidth();
int e= ip.getHeight();
for (int v=0 ; v for(int c=0; c {
int i= ip.getPixel(c,v);
K[i]=K[i]+1;

}}
ImageProcessor histIp= new ByteProcessor (500,500);
histIp.setValue(255);
histIp.fill();
for( int cont=0; cont<256; cont++)
{
int i=K[cont]/75;
for(int j=0;j {
histIp.putPixel(cont, j, 0);
}
}
ImagePlus histIm=new ImagePlus (" ", histIp);
histIm.show();
histIm.updateAndDraw();

}

}

lunes, 26 de enero de 2009

Histograma - Java

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

public class Histograma implements PlugInFilter
{
ImagePlus imp;

public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_8G + NO_CHANGES ;
}

public void run(ImageProcessor ip)
{

int [ ] H = new int [256];
int w= ip.getWidth();
int h= ip.getHeight();
for (int v=0 ; v {
for ( int u=0; u {
int i= ip.getPixel(u,v);
H[i]=H[i]+1;

}
}
ImageProcessor histIp= new ByteProcessor (500,500);
histIp.setValue(255);
histIp.fill();
for( int count=0; count<256; count++)
{
int i=H[count]/75;
for(int j=0;j {
histIp.putPixel(count, j, 0);
}
}
ImagePlus histIm=new ImagePlus ("Histograma", histIp);
histIm.show();
histIm.updateAndDraw();

}

}

viernes, 2 de enero de 2009

MANIPULACION DE IMAGENES CON FILTROS

FILTRO MEDIA

I =[25, 25, 25, 25, 25; 25, 128, 35, 35, 25; 25, 45, 35, 128, 25; 25, 25, 35, 25, 25]
[n,m]=size(I);
vec = zeros(9,1);
for i=2:n-1
for j=2:m-1
vec(1)= I(i,j);
vec(2)= I(i-1,j);
vec(3)= I(i-1,j+1);
vec(4)= I(i,j-1);
vec(5)= I(i,j);
vec(6)= I(i,j+1);
vec(7)= I(i+1,j-1);
vec(8)= I(i+1,j);
vec(9)= I(i+1,j+1);
sort(vec)
I(i,j)=vec(4)
end
end

FILTRO MEDIANA

M = [25, 25, 25, 25, 25;25,45,35,35,35;25,45,35,35,25;25,45,35,35,25;25,25,25,25,25]
[n,m]=size(M)
for i=2:n-1
for j=2:m-1

M(i,j)=fix((M(i-1,j-1)+M(i-1+j)+M(i-1,j+1)+M(i,j-1)+M(i,j)+M(i,j+1)+M(i+1,j-1)+M(i+1,j)+M (i+1,j+1))/9)

end
end