2010-04-30 9 views

risposta

20

ho finalmente trovato una soluzione al mio problema:

  1. trasformare l'immagine in scala di grigi, con ben un noto ColorMatrix.
  2. Utilizzare il metodo SetThreshold della classe ImageAttributes per impostare la soglia che separa il nero dal bianco.

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.

+4

Questo farà B/N (non in scala di grigi): 'Nuovo ColorMatrix (Nuovo singolo()() _ {Nuovo singolo() {1.5, 1.5, 1.5, 0, 0}, _ Nuovo singolo() {1.5, 1.5, 1.5 , 0, 0}, _ Nuovo singolo() {1.5, 1.5, 1.5, 0, 0}, _ Nuovo singolo() {0, 0, 0, 1, 0}, _ Nuovo singolo() {-1, - 1, -1, 0, 1}}) ' –

+1

@Otaku: No, il tuo codice non funzionerà. Darà un bordo più nitido, ma ancora valori di grigio. – Pedery

+0

@Pedery: non devi implementarlo correttamente, è esattamente come fare il bianco e nero (nessuna sfumatura di grigio qualunque). –

2

Se vuoi sembrare a metà strada decente, probabilmente vorrai applicare qualche forma di dithering.

Ecco una discussione completa, se un po 'datato:

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

+0

voglio bianco e nero perché questo sarebbe parte di un processo di riconoscimento di immagini, vale a dire avvistare alcune forme indipendentemente dalle loro colori. – vbocan

+0

In questo caso, è probabile che si possa ottenere qualcosa simile a "Pixel [x, y] = ((R (x, y) + G (x, y) + B (x, y))/3) > = 127? 1: 0 ". –

+1

Questo è quello che ho già provato, ma alterando l'immagine pixel per pixel molto lentamente. – vbocan

3

versione VB.NET:

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 
0

Quella matrice colore BW danneggia il file, da 300dpi fonte il risultato è 96 dpi con 200-300kb dimensione finale. Mi converto per giocare a Kofax, ma il TIF è corrotto per essere elaborato sul server. Anche la taglia non può essere accettata.

Il modo migliore è semplicemente cambiare la codifica in CCITT, solo BW. Il risultato rimane corretto, rimane a 300 dpi e la dimensione del file risultante è 30-50kb. Molto più efficiente e veloce di 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); 
     } 
    } 
}