Thresholding for a single RGB channel and how to put the image back together


I need to split the image to separate RGB channels, then apply a different set of thresholds on each of it, and finally put the image back together.

I’ve learned that to extract a channel I should pass rgb_channel=X, but for thresholding, RGB images with img.binary take LAB colorspace as arguments. Do I need to manually calculate LAB values of RGB thresholds for each value or is there implemented solution? To be specific, I need to cut off only the 190-255, 160-255 and 127-255 parts of the RGB image.

Also: how to put the image back together after thresholding on single channels?

Thanks for your help :slight_smile:

Hi, you want to allocate 3 extra image buffer. Use the to_grayscale() with copy_to_fb targeting one of each buffer and then a different rgb channel extraction per.

This will give you three grayscale images. You can then threshold these by doing binary(). Then b_or() the images together.

Wait, you said not binary. Anyway, when you get the three grayscale images you can threshold them. I believe we have a method that just zeros values outside of a threshold.

Not sure how to recombine. I guess you can draw_image() them all on the same output buffer using a color table to re color the grayscale back to rgb.

Thanks! I will try this out!

Ok, I have written the code that produces what I need. However, I am wondering: I store the original image in the frame buffer, and the produced rgb mask on the heap. It works for low res, but I think there would be a problem with higher resolutions - mask could possibly not fit onto the heap.

Is there a smarter way to do this?

r_th=(190, 255)

import sensor, image, time

sensor.skip_frames(time = 2000)     

    img = sensor.snapshot(copy_to_fb=True)    'src.bmp')

    img=image.Image('src.bmp', copy_to_fb=True, pause=True)
    img_buf_r=img.copy(rgb_channel=0, copy_to_fb=True)'buf_r.bmp')
    img_buf_r.binary([r_th], invert = 1)'r_mask.bmp')

    img=image.Image('src.bmp', copy_to_fb=True, pause=True)
    img_buf_g=img.copy(rgb_channel=1, copy_to_fb=True)'buf_g.bmp')
    img_buf_g.binary([g_th], invert=1)'g_mask.bmp')

    img=image.Image('src.bmp', copy_to_fb=True, pause=True)
    img_buf_b=img.copy(rgb_channel=2, copy_to_fb=True)'buf_b.bmp')
    img_buf_b.binary([b_th], invert=1)'b_mask.bmp')


    img=image.Image('src.bmp', mask=mask_rgb, copy_to_fb=True, pause=True)
    img=image.Image('src.bmp', mask=mask_rgb, copy_to_fb=True)


I’ve actually helped myself.

The answer is alloc_extra_fb. By using

mask_rgb=sensor.alloc_extra_fb(sensor.width(), sensor.height(), sensor.RGB565)`

and replacing it with command


I am able to run the b_and later on, without using the heap. Problem solved!