Pregunta

Quiero convertir una imagen de color a B / W (es decir, sin escala de grises, sólo blanco y negro). ¿Alguien tiene una buena ColorMatrix para lograr esto?

¿Fue útil?

Solución

fin he encontrado una solución a mi problema:

  1. transformar la imagen a escala de grises, usando bien un ColorMatrix conocida.
  2. Use SetThreshold método de la ImageAttributes clase para establecer el umbral que separa negro del blanco.

Este es el código C #:

using (Graphics gr = Graphics.FromImage(SourceImage)) // SourceImage is a Bitmap object
        {                
            var gray_matrix = new float[][] { 
                new float[] { 0.299f, 0.299f, 0.299f, 0, 0 }, 
                new float[] { 0.587f, 0.587f, 0.587f, 0, 0 }, 
                new float[] { 0.114f, 0.114f, 0.114f, 0, 0 }, 
                new float[] { 0,      0,      0,      1, 0 }, 
                new float[] { 0,      0,      0,      0, 1 } 
            };

            var ia = new System.Drawing.Imaging.ImageAttributes();
            ia.SetColorMatrix(new System.Drawing.Imaging.ColorMatrix(gray_matrix));
            ia.SetThreshold(0.8); // Change this threshold as needed
            var rc = new Rectangle(0, 0, SourceImage.Width, SourceImage.Height);
            gr.DrawImage(SourceImage, rc, 0, 0, SourceImage.Width, SourceImage.Height, GraphicsUnit.Pixel, ia);                
        }

He Benchmarked este código y es aproximadamente 40 veces más rápido que el píxel por píxel manipulación.

Otros consejos

VB.NET versión:

Using gr As Graphics = Graphics.FromImage(SourceImage) 'SourceImage is a Bitmap object'
  Dim gray_matrix As Single()() = {
    New Single() {0.299F, 0.299F, 0.299F, 0, 0},
    New Single() {0.587F, 0.587F, 0.587F, 0, 0},
    New Single() {0.114F, 0.114F, 0.114F, 0, 0},
    New Single() {0, 0, 0, 1, 0},
    New Single() {0, 0, 0, 0, 1}
  }
  Dim ia As New System.Drawing.Imaging.ImageAttributes
  ia.SetColorMatrix(New System.Drawing.Imaging.ColorMatrix(gray_matrix))
  ia.SetThreshold(0.8)
  Dim rc As New Rectangle(0, 0, SourceImage.Width, SourceImage.Height)
  gr.DrawImage(SourceImage, rc, 0, 0, SourceImage.Width, SourceImage.Height, GraphicsUnit.Pixel, ia)
End Using

Si usted quiere que se vea medianamente decente, es probable que desee aplicar algún tipo de tramado.

Aquí hay una discusión completa, aunque un poco anticuado:

http://www.efg2.com/Lab/Library/ImageProcessing /DHALF.TXT

Usted no necesita una matriz de color a achive esto, sólo basta con cambiar la codificación CCITT! Que sólo Blanco y Negro. El resultado sigue siendo correcta y el tamaño de archivo de resultados es muy pequeña. También mucho más eficiente y más rápido que System.DrawImage.

Esta es la solución perfecta:

public void toCCITT(string tifURL)
{
    byte[] imgBits = File.ReadAllBytes(tifURL);

    using (MemoryStream ms = new MemoryStream(imgBits))
    {
        using (Image i = Image.FromStream(ms))
        {
            EncoderParameters parms = new EncoderParameters(1);
            ImageCodecInfo codec = ImageCodecInfo.GetImageDecoders()
                                                 .FirstOrDefault(decoder => decoder.FormatID == ImageFormat.Tiff.Guid);

            parms.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT4);

            i.Save(@"c:\test\result.tif", codec, parms);
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top