Patrocinado por:
Ir Atrás   LANeros.com / Foro / Blogs / JuanK_solocodigo


Califica esta Entrada

C# - XNA- Como Convertir Una Imagen a Escala de Grises

Publicado noviembre 29, 2009 a las 11:47 por JuanK_solocodigo
Actualizado diciembre 3, 2009 a las 09:25 por JuanK_solocodigo

Hola, nuevamente les comparto uno de los artículos de mi blog!

Este articulo es una copia cruzada de mi blog original, visítalo en:

http://juank.black-byte.com/xna-conv...escala-grises/


-------------------
Hola, este artículo abordara un problema relativamente sencillo, aplicar a una imagen un efecto para verla en escala de grises.

Este tema, aunque sencillo, es muy necesario para adentrarse un poco más en el procesamiento digital de imágenes ,lo cual desde liego estaré trabajando dentro de poco en el blog.

Para este artículo he decidido utilizar XNA Framework, pero bien habría podido utilizar un PictureBox o un objeto Bitmap o cualquier otro conjunto de objetos existentes en el .Net Framework, incluso podría haber escogido simplemente leer un archivo analizarlo, convertirlo y luego escribirlo de nuevo. He escogido XNA simplemente porque es la tecnología más adecuada para exponer este tipo de temas y es donde sin duda muchos de ustedes querrán aplicar estos temas.

Cómo Convertir una Imagen a Escala de Grises

Básicamente para que una imagen sea vea en tonos de gris se requiere que los tres componentes básicos del color ( en el computador: rojo, verde, azul – RGB por sus siglas en ingles ) tengan más o menos la misma intensidad, podemos decir que si queremos convertir un pixel a su equivalente en escala de grises bastaría con hacer algo como esto:

  1. Sumar los valores de los componentes de color del pixel, es decir sumar R + G + B
  2. Sacar el promedio de esa suma
  3. El valor hallado se debe asignar a R, G y B
Con estos tres pasos ya logramos que el pixel sea de color gris ya que cada uno de sus componentes tiene el mismo valor.

Hay muchas otras formas de hacerlo, incluso alguien que haya trabajado previamente con imágenes puede tener su propia versión de como implementarlo de acuerdo a lo que necesite o al tiempo que tenga. Pero existe una manera ampliamente conocida y aceptada en el gremio de las personas que trabajan con imágenes y visión por computador esa manera es la que aprenderemos a efectuar.

El ojo humano y su sensibilidad

Bien, resulta que el ojo humano es mucho más sensible a los colores verdes y rojos que al azul, por lo que en cuanto a percepción de iluminación se trata nuestro ojo reconoce los patrones de iluminación en color en las siguientes proporciones para cada componente:

  • Rojo:30%
  • Verde:59%
  • Azul:11%

Así que lo más adecuado es calcular el valor de cada componente de color con base a esta proporción y de este modo se obtiene el pixel de color gris con la iluminación adecuada para que nuestro ojo lo perciba como un mejor equivalente a su versión en color.

Manos A La Obra, Tiempo de Programar

Bueno, la idea de este artículo no es mostrar como poner imágenes en pantalla con XNA pero un super repaso no sienta nada mal.

Para utilizar la técnica que he planteado lo primero que se debe hacer es cargar la imagen, en XNA esto se hace con un Objeto Texture2D, al cual le asignaremos una imagen traída desde el Content:
Código PHP:
 protected override void LoadContent()
        {
            
// Create a new SpriteBatch, which can be used to draw textures.
            
spriteBatch = new SpriteBatch(GraphicsDevice);
 
            
// TODO: use this.Content to load your game content here
            
conejo Content.Load<Texture2D>("Imagenes/conejo");
        } 
Y para dibujar esta imagen basta con hacer esto:
Código PHP:
 protected override void Draw(GameTime gameTime)
        {
            
GraphicsDevice.Clear(Color.CornflowerBlue);
 
            
// TODO: Add your drawing code here
            
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
 
            
spriteBatch.Draw(imagenEfectivaVector2.ZeroColor.White);
 
            
spriteBatch.End();
 
            
base.Draw(gameTime);
        } 
Este es el resultado en pantalla:


Ahora comienza el verdadero trabajo. Implementaré un método que nos cree una copia de la imagen, pero en escala de grises, este método recibe como parámetro nuestra textura original (es decir la imagen).

Lo primero que se debe hacer es crear una nueva Texture2D de las mismas dimensiones que la Texture2D original, para utilizarla como lienzo, donde se dibujara la nueva imagen en escala de grises.
Código PHP:
 public Texture2D GrayScale(Texture2D source)
        {
            
Texture2D target = new Texture2D(source.GraphicsDevicesource.Widthsource.Height);
            
            return 
target;
        } 
Para poder dibujar en esta textura es necesario acceder a su información (sus pixeles) esto se hace con el método genérico GetData el cual se puede utilizar para obtener un array de bytes con la información de cada punto color.
El formato de color que utiliza Texture2D es por defecto color de 32 bit RGBA (la A es de Alpha para las transparencias… no nos importa ahora) así que GetData nos devuelve un array de bytes utilizando 4 bytes para cada punto de color de la imagen, por lo cual la capacidad de el array de bytes debe ser 4 * ancho * alto de la imagen.
Código PHP:
 public Texture2D GrayScale(Texture2D source)
        {
            
Texture2D target = new Texture2D(source.GraphicsDevicesource.Widthsource.Height);
            
            
byte[] data = new byte[source.Width source.Height 4];
 
            
source.GetData<byte>(data);
 
 
            return 
target;
        } 
Ahora se debe recorrer al array de bytes de pixel en pixel ( es decir en saltos de a 4 bytes ) sabiendo que los 3 primeros bytes de cada grupo de 4 son respectivamente R, G y B, de tal forma que multiplicamos el valor de cada byte por el valor de la proporción de iluminación, este es el valor de la intensidad asi que asignamos a cada uno de los tres bytes el valor de iluminación que hemos hallado
Código PHP:
 public Texture2D GrayScale(Texture2D source)
        {
            
byte y 0;
            
Texture2D target = new Texture2D(source.GraphicsDevicesource.Widthsource.Height);
            
            
byte[] data = new byte[source.Width source.Height XNA_COLOR_DEPTH];
 
            
source.GetData<byte>(data);
 
            for (
int i 0data.Length+= 4)
            {
                
// Y = R * 0.3 + G * 0.59 + B * 0.11
                
= (byte)(data[i] * 0.11f data[1] * 0.59f data[2] * 0.3f);
                
data[2] = data[1] = data[i] = y;
            }
 
            return 
target;
        } 
Finalmente se utiliza el método genérico SetData de la Texture2D para asignar a la textura el array de bytes modificado.
Código PHP:
 public Texture2D GrayScale(Texture2D source)
        {
            
byte y 0;
            
Texture2D target = new Texture2D(source.GraphicsDevicesource.Widthsource.Height);
            
            
byte[] data = new byte[source.Width source.Height XNA_COLOR_DEPTH];
 
            
source.GetData<byte>(data);
 
            for (
int i 0data.Length+= 4)
            {
                
// Y = R * 0.3 + G * 0.59 + B * 0.11
                
= (byte)(data[i] * 0.11f data[1] * 0.59f data[2] * 0.3f);
                
data[2] = data[1] = data[i] = y;
            }
            
target.SetData<byte>(data);
            return 
target;
        } 
La implementación definitiva puede quedar así:
Código PHP:
 public Texture2D GrayScale(Texture2D source)
        {
            
Texture2D target = new Texture2D(source.GraphicsDevicesource.Widthsource.Height);
            
            
byte[] data = new byte[source.Width source.Height XNA_COLOR_DEPTH];
 
            
source.GetData<byte>(data);
 
            for (
int i 0data.Length+= 4)
                
data[2] = data[1] = data[i] = (byte)(data[i] * 0.11f data[1] * 0.59f data[2] * 0.3f);
 
            
target.SetData<byte>(data);
 
            return 
target;
        } 
Utilizando este método podemos entonces crear una textura que sea la representación en escala de grises de otra, lo cual al ponerlo en pantalla sería así:


Eso es todo!!

En este otro artículo muestro como hacer lo mismo pero con Bitmap y PictureBox:

http://juank.black-byte.com/c-bitmap-convertir-imagen-escala-grises/
Publicado en Sin Categorizar
Visitas 668 Comentarios 0 Enviar Entrada de Blog a un Amigo
« Ant.     Principal     Sig. »
Total de Comentarios 0

Comentarios

 
Total de Trackbacks 0

Trackbacks


¿Nuevo en el sitio? ¿Buscando Ayuda?

Todas las horas son GMT -5. La hora actual es 08:01 .


vBulletin System 3.8.5 - Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.