Voglio convertire un'immagine da colore a bianco e nero (vale a dire senza scala di grigi, solo bianco e nero). Qualcuno ha una buona colormatrice per raggiungere questo obiettivo?Quale sarebbe una buona colormatrix TRUE in bianco e nero?
risposta
ho finalmente trovato una soluzione al mio problema:
- trasformare l'immagine in scala di grigi, con ben un noto ColorMatrix.
- 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.
Se vuoi sembrare a metà strada decente, probabilmente vorrai applicare qualche forma di dithering.
Ecco una discussione completa, se un po 'datato:
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
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 ". –
Questo è quello che ho già provato, ma alterando l'immagine pixel per pixel molto lentamente. – vbocan
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
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);
}
}
}
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}}) ' –
@Otaku: No, il tuo codice non funzionerà. Darà un bordo più nitido, ma ancora valori di grigio. – Pedery
@Pedery: non devi implementarlo correttamente, è esattamente come fare il bianco e nero (nessuna sfumatura di grigio qualunque). –