Python 在 PIL 中更改图像的对比度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42045362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 21:09:12  来源:igfitidea点击:

Change contrast of image in PIL

pythonpython-3.xpython-imaging-library

提问by Megzari Nassim

I have a program that's supposed to change the contrast, but I feel like it's not really changing the contrast.It changes some areas to red whereas I don't want it to. If you could tell me how to remove them, thank you. Here is the code:

我有一个应该改变对比度的程序,但我觉得它并没有真正改变对比度。它把一些区域变成了红色,而我不希望它变成红色。如果你能告诉我如何删除它们,谢谢。这是代码:

from PIL import Image


def change_contrast(img, level):

    img = Image.open("C:\Users\omar\Desktop\Site\Images\obama.png")
    img.load()

    factor = (259 * (level+255)) / (255 * (259-level))
    for x in range(img.size[0]):
        for y in range(img.size[1]):
            color = img.getpixel((x, y))
            new_color = tuple(int(factor * (c-128) + 128) for c in color)
            img.putpixel((x, y), new_color)

    return img

result = change_contrast('C:\Users\omar\Desktop\Site\Images\test_image1.jpg', 100)
result.save('C:\Users\omar\Desktop\Site\Images\test_image1_output.jpg')
print('done')

And here is the image and its result:

这是图像及其结果:

obama.pngobama modified

奥巴马.png奥巴马修改

If this is the actual contrast method, feel free to tell me

如果这是实际的对比方法,请随时告诉我

回答by H?ken Lid

I couldn't reproduce your bug. On my platform (debian) only the Pillow fork is available, so if you are using the older PIL package, that might be the cause.

我无法重现您的错误。在我的平台 (debian) 上,只有 Pillow fork 可用,因此如果您使用的是较旧的 PIL 包,这可能是原因。

In any case, there's a built in method Image.point()for doing this kind of operation. It will map over each pixel in each channel, which should be faster than doing three nested loops in python.

在任何情况下,都有一个内置的方法Image.point()来执行这种操作。它将映射每个通道中的每个像素,这应该比在 python 中执行三个嵌套循环更快。

def change_contrast(img, level):
    factor = (259 * (level + 255)) / (255 * (259 - level))
    def contrast(c):
        return 128 + factor * (c - 128)
    return img.point(contrast)

change_contrast(Image.open('barry.png'), 100)

output

输出

Your output looks like you have a overflow in a single channel (red). I don't see any reason why that would happen. But if your levelis higher than 259, the output is inverted. Something like that is probably the cause of the initial bug.

您的输出看起来像是在单个通道中溢出(红色)。我看不出有什么理由会发生这种情况。但是如果你的level值高于 259,输出就会反转。这样的事情可能是最初错误的原因。

def change_contrast_multi(img, steps):
    width, height = img.size
    canvas = Image.new('RGB', (width * len(steps), height))
    for n, level in enumerate(steps):
        img_filtered = change_contrast(img, level)
        canvas.paste(img_filtered, (width * n, 0))
    return canvas

change_contrast_multi(Image.open('barry.png'), [-100, 0, 100, 200, 300])

another output

另一个输出

A possible fix is to make sure the contrast filter only return values within the range [0-255], since the bug seems be caused by negative values overflowing somehow.

一个可能的解决方法是确保对比度过滤器只返回 [0-255] 范围内的值,因为该错误似乎是由以某种方式溢出的负值引起的。

def change_contrast(img, level):
    factor = (259 * (level + 255)) / (255 * (259 - level))
    def contrast(c):
        value = 128 + factor * (c - 128)
        return max(0, min(255, value))
    return img.point(contrast)

回答by orvi

There's already built a class called contrastin PIL module. You can simply use it.

在 PIL 模块中已经构建了一个名为contrast的类。你可以简单地使用它。

from PIL import Image, ImageEnhance
image = Image.open(':\Users\omar\Desktop\Site\Images\obama.png')
scale_value=scale1.get()
image = ImageEnhance.Contrast(image).enhance(scale_value)
image.show()