Grayscale to binary image conversion

Started by
10 comments, last by wlw_wl 15 years, 11 months ago
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?
Advertisement
Check out error diffusion.
There is also Dithering
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?
I am no expert but are you sure you have to compare it to 0.5? Have you looked at the pseudo code example here: Floyd-Steinberg Dithering
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.
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.
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.
Nope haven't changed anything, maybe you were on a different resolution?
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.

This topic is closed to new replies.

Advertisement