I want to convert an image from color to B/W (i.e. no grayscale, just black and white). Does anyone have a good colormatrix to achieve this?
A:
If you want it to look halfway decent, you'll probably want to apply some form of dithering.
Here's a full discussion, if a bit dated:
500 - Internal Server Error
2010-04-30 18:06:51
I want black and white because this would be part of an image recognition process, i.e. spotting some shapes regardless of their colors.
vbocan
2010-04-30 19:12:27
In that case, you can probably get away with something along the lines of "Pixel[x, y] = ((R(x, y) + G(x, y) + B(x, y)) / 3) >= 127 ? 1 : 0".
500 - Internal Server Error
2010-04-30 20:32:16
This is what I've already tried, but altering the image pixel by pixel in very slow.
vbocan
2010-05-03 08:33:01
+1
A:
I've finally found a solution to my problem:
- Transform the image to grayscale, using well a known colormatrix.
- Use SetThreshold method of the ImageAttributes class to set the threshold that separates black from white.
Here is the C# code:
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);
}
I've benchmarked this code and it is approximately 40 times faster than pixel by pixel manipulation.
vbocan
2010-05-03 09:02:41
Otaku
2010-06-11 20:54:24