Sign in to follow this  
wlw_wl

Grayscale to binary image conversion

Recommended Posts

Hello, I searched quite a lot but I haven't found any dtailed information about how to transform a grayscale image into binary image that looks as much the same as possible. I found some implementations but none of them seemed to work fine. For example, when the input is a 64x64 bitmap with all pixels at 0.5 I want to output a checker, which is the nearest to the original (what I got from the methods I found was all black or all white). I developed a texture-compression-like approach where I pass the image with a sub-frame of, for example, 4 by 4 pixels (Initially all pixels in the uotput are black). In such a frame, I add values of all pixels and round it to integer (let's call it N). N is the number of pixels in the frame that has to be white in the output. So i make the corresponding pixel which has the maxmum value white and decrease N, and repeat this until N is 0. Seems logical to me, but when the input is all pixels 0.5, the output is horizontal black and white lines instead of a checker. What would be a better and all-purpose algorithm to convert grayscale into binary image?

Share this post


Link to post
Share on other sites
Thanks, that helped a lot!

But I'm not sure about following thing:

in error diffusion, I compare each pixel in the input to a 0.5 value and set it 1.0 or 0.0 and then diffuse the error (let's say the Floyd-Steinberg way), but this won't give me the binary values, so do I make the comparison to 0.5 (or some other threshold) again?

Share this post


Link to post
Share on other sites
I guess that is what I should do, as it is in that pseudocode:

newpixel := find_closest_palette_color(oldpixel)

because my palette is only black (0.0) and white (1.0), I find nearest color by comparing the value to 0.5

wonder why the Floys-Steinberg method has different distribution matrices in different articles...


Oh, And I've answered my previous question myself, so it's out-of-date.

Share this post


Link to post
Share on other sites
Quote:
I compare each pixel in the input to a 0.5 value and set it 1.0 or 0.0 and then diffuse the error (let's say the Floyd-Steinberg way), but this won't give me the binary values, so do I make the comparison to 0.5 (or some other threshold) again?

After reading a bit more I now understand what you are saying. What you are doing is thresholding the current pixel to 0 or 1 and dispersing the error to the neighbouring pixels. When you go the x+1 pixel that value is no longer 0.5, its 0.5 + error, so you threshold that pixel and add the error to the surrounding pixels again and so on.
I found these notes better at explaining things than just the pseudo code:
Floyd-Steinberg Dithering
I managed to get my own implementation going that converted this 32 bit gray scale image:
Gradient
To a 1 bit binary image
Floyd-Steinberg Dithering
Basically using this code
for (int y = 1; y < height-1; y++) {
offset =y*width;
for (int x=1; x < width-1; x++) {
pos = offset + x;
//oldpixel := pixel[x][y]
oldPixel = pixels[pos];

//newpixel := find_closest_palette_color(oldpixel)
newPixel = (oldPixel >= 0.5)?1.0f : 0.0f;

//pixel[x][y] := newpixel
pixels[pos] = newPixel ;

//quant_error := oldpixel - newpixel
quant_error = oldPixel - newPixel;

//pixel[x+1][y] := pixel[x+1][y] + 7/16 * quant_error
pixels[pos + 1] += 7.0f/16.0f * quant_error;

//pixel[x-1][y+1] := pixel[x-1][y+1] + 3/16 * quant_error
pixels[pos - 1 + width] += 3.0f/16.0f * quant_error;

//pixel[x][y+1] := pixel[x][y+1] + 5/16 * quant_error
pixels[pos + width] += 5.0f/16.0f * quant_error;

//pixel[x+1][y+1] := pixel[x+1][y+1] + 1/16 * quant_error
pixels[pos + 1 + width] += 1.0f/16.0f * quant_error;
}
}

Although apparently you are suppose to go in a zig zag motion rather than a left to right motion that I did. Not really sure why but hope that helps.

Share this post


Link to post
Share on other sites
4fingers, have you changed anything since you wrote your post?

The image looks much better than the original I saw, that one had some bad artifacts... I'm not sure if it's a different image or is it that I'm viewing it on some other machine.

Share this post


Link to post
Share on other sites
Yes, and it was LCD and now I'm viewing it on my CRT and it's what it was, a huge difference though. I'll be coding this today or tomorrow so I'll post what I've managed to do.

Share this post


Link to post
Share on other sites
The reason for zigzagging is to avoid the artifact you've got in the top-left corner of your monochrome image; where there's no visible dithering for a fair while, because the algorithm hasn't yet accumulated enough error to dither properly.

Share this post


Link to post
Share on other sites
Well, I've implemented Floyd-Steinberg, Stucki, Sierra 3 and Ninke and I noticed that this zig-zag movement that should be done destroys the image totally.

Thanks for all replies, they were a great aid!

It's a shame, but I don't know how to do that:

I get my image in two-dimmensional array and I want to save it as a .bmp file, but CreateBitmap function gives me a hard time... How should I do that?

[Edited by - wlw_wl on May 16, 2008 7:40:48 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this