Изменение контрастности изображения в PIL

У меня есть программа, которая должна изменить контраст, но я чувствую, что она на самом деле не меняет контраст.Он меняет некоторые области на красные, тогда как я этого не хочу. Если бы вы могли сказать мне, как их удалить, спасибо. Вот код:

from PIL import Image


def change_contrast(img, level):

    img = Image.open("C:UsersomarDesktopSiteImagesobama.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:UsersomarDesktopSiteImagestest_image1.jpg', 100)
result.save('C:UsersomarDesktopSiteImagestest_image1_output.jpg')
print('done')

и вот изображение и его результат:

obama.png obama modified

Если это фактический метод контраста, не стесняйтесь говорить мне

2 ответов


Я не смог воспроизвести вашу ошибку. На моей платформе (debian) доступна только вилка подушки, поэтому, если вы используете более старый пакет PIL, это может быть причиной.

в любом случае, есть встроенный метод 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

ваш выход выглядит так, как будто у вас есть переполнение в одноканальный (красный). Я не вижу причин, по которым это могло бы произойти. Но если ваш 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

возможное исправление - убедиться, что фильтр контрастности возвращает только значения в диапазоне [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)

уже построен класс под названием контраст в модуле PIL. Вы можете просто использовать его.

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