Domanda

Voglio convertire un'immagine da colore a B / W (vale a dire non in scala di grigi, solo bianco e nero). Qualcuno ha un buon ColorMatrix per raggiungere questo obiettivo?

È stato utile?

Soluzione

Ho finalmente trovato una soluzione al mio problema:

  1. trasformare l'immagine in scala di grigi, utilizzando anche un ColorMatrix noto.
  2. Usa SetThreshold il metodo del ImageAttributes di classe per impostare la soglia che separa il bianco dal nero.

Ecco il codice 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);                
        }

Ho benchmark questo codice ed è circa 40 volte più veloce di pixel per la manipolazione dei pixel.

Altri suggerimenti

VB.NET versione:

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

Se si desidera guardare decente, probabilmente si vorrà applicare una qualche forma di dithering.

Ecco una discussione completa, se un po 'datato:

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

Non avete bisogno di una matrice di colore per raggiungere questo obiettivo, semplicemente cambiare la codifica a CCITT! Che solo in bianco e nero. Risultato rimane corretta e dimensione del file risultato è molto piccolo. Anche molto più efficace e più rapido System.DrawImage.

Questa è la soluzione perfetta:

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);
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top