Skip to content Skip to sidebar Skip to footer

Python: How To Implement Binary Filter On Rgb Image? (algorithm)

I'm trying to implement binary image filter (to get monochrome binary image) using python & PyQT5, and, to retrieve new pixel colors I use the following method: def _new_pixel_

Solution 1:

I would at least compare against intensity i=R+G+B ...

For ROI like masks you can use any thresholding techniques (adaptive thresholding is the best) but if your resulting image is not a ROI mask and should resemble the visual features of the original image then the best conversion I know of is to use Dithering.

The Idea behind BW dithering is to convert gray scales into BW patterns preserwing the shading. The result is often noisy but preserves much much more visual details. Here simple naive C++ dithering (sorry not a Python coder):

picture pic0,pic1;
    // pic0 - source img// pic1 - output imgint x,y,i;
color c;
// resize output to source image size clear with black
pic1=pic0; pic1.clear(0);
// dithering
i=0;
for (y=0;y<pic0.ys;y++)
 for (x=0;x<pic0.xs;x++)
    {
    // get source pixel color (AARRGGBB)
    c=pic0.p[y][x];
    // add to leftovers
    i+=WORD(c.db[picture::_r]); // _r,_g,_b are just constants 0,1,2
    i+=WORD(c.db[picture::_g]);
    i+=WORD(c.db[picture::_b]);
    // threshold white intensity is 255+255+255=765if (i>=384){ i-=765; c.dd=0x00FFFFFF; } else c.dd=0;
    // copy to destination image
    pic1.p[y][x]=c;
    }

So its the same as in the link above but using just black and white. i is the accumulated intensity to be placed on the image. xs,ys is the resolution and c.db[] is color channel access.

If I apply this on colored image like this:

input

The result looks like this:

output

As you can see all the details where preserved but a noisy patterns emerge ... For printing purposes was sometimes the resolution of the image multiplied to enhance the quality. If you change the naive 2 nested for loops with a better pattern (like 16x16 squares etc) then the noise will be conserved near its source limiting artifacts. There are also approaches that use pseudo random patterns (put the leftover i near its source pixel in random location) that is even better ...

But for a BW dithering even naive approach is enough as the artifacts are just one pixel in size. For colored dithering the artifacts could create unwanted horizontal line patterns of several pixels in size (depends on used palette mis match the worse palette the bigger artifacts...)

PS just for comparison to other answer threshold outputs this is the same image dithered:

inputoutput

Solution 2:

Image thresholding is the class of algorithms you're looking for - a binary threshold would set pixels to 0 or 1, yes.

Depending on the desired output, consider converting your image first to other color spaces, in particular HSL, with the luminance channel. Using (127, 127, 127) as a threshold does not uniformly take brightness into account because each channel of RGB is the saturation of R, G, or B; consider this image:

Original Image

127, 127, 127 RGB Threshold

50% Luminance HSL Threshold

from PIL import Image
import colorsys


defthreshold_pixel(r, g, b):
    h, l, s = colorsys.rgb_to_hls(r / 255., g / 255., b / 255.)
    return1if l > .36else0# return 1 if r > 127 and g > 127 and b > 127 else 0defhlsify(img):
    pixels = img.load()
    width, height = img.size

    # Create a new blank monochrome image.
    output_img = Image.new('1', (width, height), 0)
    output_pixels = output_img.load()

    for i inrange(width):
        for j inrange(height):
            output_pixels[i, j] = threshold_pixel(*pixels[i, j])

    return output_img


binarified_img = hlsify(Image.open('./sample_img.jpg'))
binarified_img.show()
binarified_img.save('./out.jpg')

There is lots of discussion on other StackExchange sites on this topic, e.g.

Binarize image data

How do you binarize a colored image?

how can I get good binary image using Otsu method for this image?

Post a Comment for "Python: How To Implement Binary Filter On Rgb Image? (algorithm)"