简体   繁体   中英

Pixel to pixel edit using PIL and Image.point

I can't seem to understand what Image point does. I want to do some pixel edit which might include checking which color value(r, g or b) is max in every pixel and act accordingly. Lets say that I can't use numpy. I managed to use Image point to add the same value to every pixel in an image. point code

import Image, math

def brightness(i, value):
value = math.floor(255*(float(value)/100))
return i+value

if __name__ == '__main__':
    image = '/home/avlahop/verybig.jpg'
    print image
    img = Image.open(image)
    print img
    out = img.point(lambda i: brightness(i, 50))
    out.show()

numpy code

def brightness(arr, adjust):
    import math
    adjust = math.floor(255*(float(adjust)/100))


    arr[...,0] += adjust
    arr[...,1] += adjust
    arr[...,2] += adjust
    return arr

if __name__ == '__main__':
    image = '/home/avlahop/verybig.jpg'
    img = Image.open(image).convert('RGBA')
    arr = np.array(np.asarray(img).astype('float'))
    new_image = Image.fromarray(brightness(arr, adjust).clip(0,255).astype('uint8'), 'RGBA').show()

I have to say that point code is faster than numpy's. But what if i want to do a more complex operation with point. for example for every pixel check the max(r,g,b) and do something depending on if r=max or g=max or b=max. As you saw i used the point with function as argument. It takes one argument i. what is this i? is it the pixel?(ie i=(r,g,b)?).I can't seem to understand from the pil documentation

The docs may not have been clear in earlier versions of PIL, but in Pillow it's spelled out pretty well. From Image.point :

lut – A lookup table, containing 256 values per band in the image. A function can be used instead, it should take a single argument. The function is called once for each possible pixel value, and the resulting table is applied to all bands of the image.

In other words, it's not a general-purpose way to map each pixel through a function, it's just a way to dynamically built the lookup table, instead of passing in a pre-built one.

In other words, it's called with the numbers from 0 through 255 . (Which you can find out for yourself pretty easily by just writing a function that appends its argument to a global list and then dump out the list at the end…)

If you split your image into separate bands or planes, point each one of them with a different function, and then recombine them, that might be able to accomplish what you're trying to do. But even then, I think eval is what you wanted, not point .

But I think what you really want, which is a pixel-by-pixel all-bands-at-once iterator. And you don't need anything special for that. Just use map or a comprehension over getdata . Isn't that slow? Of course it's slow, because it's calling your function X*Y times; the cost of building the getdata sequence and iterating over it is tiny compared to that cost, so looking for a way for PIL to optimize the already-fast-enough part won't get you very far.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM