简体   繁体   中英

Gamma correction with Pillow Image turning to Grayscale

Trying to perform gamma correction on an image in a dash app. But original color images turn to grayscale after going through my function. I'm using Pillow Image.new("P", ...) for color instead of "L" which would be for gray scale. And if I use Image.new("RGB",...) the returned image is red. Please help.

def gamma_correct(gamma, url):
    im = Image.open(requests.get(url, stream=True).raw)
    
    gamma1 = gamma
    row = im.size[0]
    col = im.size[1]
    result_img1 = Image.new("RGB", (row, col))
    for x in range(1 , row):
        for y in range(1, col):
            r = pow(im.getpixel((x,y))[0]/255, (1/gamma1))*255
            g = pow(im.getpixel((x,y))[1]/255, (1/gamma1))*255
            b = pow(im.getpixel((x,y))[2]/255, (1/gamma1))*255
            result_img1.putpixel((x,y)[0], int(r))
            result_img1.putpixel((x,y)[1], int(g))
            result_img1.putpixel((x,y)[2], int(b))

Bear in mind "P" and "RGB" are not the same. P is palette mode, and is limited to 256 colours.

Colour images have these dimensions: (width, tall, channels), with channels usually being = 3.

It seems like you are saving the image, with all colour values in a single channel, meaning you end up with an image like (width, tall, channels) with channel = 1. This is also the reason why you get a red image when you use Image.new("RGB",...), since your image has data only in the first channel (R)


@ChristophRackwitz is correct in both his comments. Most often, libraries handling images actually handle the dimensions (height, width, channels), so if you load an image from disk which is, say, (1920,1080,3), the object in memory actually has dimensions (1080,1920,3). Additionally, some software (like opencv) even treat channels as BGR isntead of RGB by default

RGB images have 3 channels, which are the values of each colour. This means that for each pixel in the image, there are 3 colour values, one for red channel (R), one for green (G) and one for blue (B)

try debugging the image modification process, ie:

for x in range(1 , row):
    for y in range(1, col):
            print(im.getpixel(x,y))
            r = pow(im.getpixel((x,y))[0]/255, (1/gamma1))*255
            g = pow(im.getpixel((x,y))[1]/255, (1/gamma1))*255
            b = pow(im.getpixel((x,y))[2]/255, (1/gamma1))*255
            print(im.getpixel(x,y))

The two print statements will print a 3-dimension array. Check that the values of each channel are as expected, both before and after

bro, The error is that you are only passing one channel (that's R) parameter to the putpixel() method. You need to pass a tuple of RGB values.

def gamma_correct(gamma, path):
    im = Image.open(path)
    gamma1 = gamma
    row = im.size[0]
    col = im.size[1]
    result_img1 = Image.new(mode="RGB", size=(row, col), color=0)
    for x in range(row):
        for y in range(col):
            r = pow(im.getpixel((x, y))[0] / 255, (1 / gamma1)) * 255
            g = pow(im.getpixel((x, y))[1] / 255, (1 / gamma1)) * 255
            b = pow(im.getpixel((x, y))[2] / 255, (1 / gamma1)) * 255
            # add
            color = (int(r), int(g), int(b))
            result_img1.putpixel((x, y), color)
    #show
    result_img1.show()

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