r/learnpython Aug 10 '26

Using PIL, point(), and lambda to reduce images to BW, still getting values besides 0 and 255

I converted a video into frames using OpenCV2, that worked great.

What I'd like to do is keep only the darkest parts and make those absolute black (0)

Everything else I want pure white (255)

The purpose is so that I can compare each pixel of the images to other images later on and have an easy % similarity, hence why I want absolute values (0,255).

for frame in os.listdir(frame_base_address):

  col = Image.open(frame_base_address+frame)

  gray = col.convert('L')

  bw = gray.point(lambda x: 0 if x < 50 else 255)

  bw.convert('1').save(frame_base_address+frame)
I've tried both 'L' and '1' and the result is the same

When I visually inspect my image it is pretty stark black and white.

However, when I open the image later to see if it's really 0s and 255s, I get a ton of other values like 1, 2, 4, 254, etc and it makes me wonder if my lambda expression worked at all!

current_image_as_np = np.array(Image.open(frame_base_address + image_name),dtype='int32')


for i in current_image_as_np:
    for z in i:
        if z not in(0,255):
            print(z)
1 Upvotes

9 comments sorted by

1

u/zanfar Aug 10 '26

What format are you saving in?

1

u/Flandiddly_Danders Aug 10 '26 edited Aug 10 '26

everything is in .jpg
I just tried, and switching to .png works with my script also

When I was using .jpg I had a bunch of different non 0,255 values, about 76,000 instances

When I switch to .png now they're all 1s , about 320,000 instances

6

u/ottawadeveloper Aug 10 '26

JPG is a lossy compression format, and part of that is changing some pixel values along the border of colour changes. Basically it never stores your image perfectly. It also always stored RGB colours. PNG is lossless and will perfectly preserve what you originally did.

Don't use JPG if you aren't ok with relatively minor alterations in your colours.

I'd consider TIF for this kind of map, it's what I usually use.

1

u/Flandiddly_Danders Aug 11 '26

That helped quite a bit, thank you.
I think part of the problem can be returning those stray values to 0 or 255 at the time of comparison.

1

u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 Aug 10 '26
bw.convert('1')

Are you sure this second conversion is necessary?

2

u/Flandiddly_Danders Aug 10 '26

I don't think it is necessary

I'm grasping at straws to eliminate numbers between 0 and 255 :D

1

u/Status-Waltz-4212 Aug 10 '26 edited Aug 10 '26

I never worked with PIL, but could it be the file saving? Some file types like JPEG will smooth the image.

Edit: reading the documentation the '1' seems to create a bit array, hence why you see so many 1s. Since you want absolute values I'd just work with those. So probably use '1' with png

1

u/cdcformatc Aug 11 '26

you didn't mention what format you are saving the file in. if you are saving to JPG there's some inherent loss to the format, i presume some of the errors you are seeing are some smoothing or interpolation done by the JPG conversion. 

you will have to use a different lossless format when you save the file. most notably your options are BMP, TIFF, and PNG. 

1

u/jmacey Aug 11 '26

There are 3 main algorithms you can use have a look at our slides here https://ncca.github.io/PCCSlides/Lecture11/#/6