Осветление или затемнение изображений в PIL без встроенных функций

1

Я использую PIL для проекта uni, и у нас есть одна задача, когда мы должны темнее или ярче изображения без использования каких-либо функций PIL для этого. Функция принимает исходное имя файла, действие ( "светить" или "затемнить" ) и степень (в процентах - от интервала между 0 и 100). Вот что я до сих пор придумал:

from PIL import Image

def change_brightness(filename, action, extent):
    """
    This function either increases or decreases the brightness of an image
    by altering each pixel in each band

    """
    #load the original image into a list
    original_image = Image.open(filename, 'r')
    pixels = original_image.getdata()

    #initialise the new image
    new_image = Image.new('RGB', original_image.size)
    new_image_list = []

    brightness_multiplier = 1.0

    if action == 'lighten':
        brightness_multiplier += (extent/100)
    else:
        brightness_multiplier -= (extent/100)

    #for each pixel, append the brightened or darkened version to the new image list
    for pixel in pixels:
        new_pixel = (int(pixel[0] * brightness_multiplier),
                     int(pixel[1] * brightness_multiplier),
                     int(pixel[2] * brightness_multiplier))

        #check the new pixel values are within rgb range
        for pixel in new_pixel:
            if pixel > 255:
                pixel = 255
            elif pixel < 0:
                pixel = 0

        new_image_list.append(new_pixel)

    #save the new image
    new_image.putdata(new_image_list)
    new_image.save('colour_brightness.jpg')

Когда я запускаю это, новое изображение не изменяется от оригинала (кроме некоторых новых артефактов jpg). Я пробовал brightness_multiplier с явным значением (1.1 для lighten и 0.9 для darken), и он работал, поэтому я понятия не имею, почему он не работает, когда у меня есть значение из аргумента extent.

Если кто-то может пролить некоторый свет, мы будем очень благодарны!

  • 0
    Я только что понял это! Мне пришлось изменить 100 в (extent/100) на поплавок, и это сработало! Я пока не могу ответить на свой вопрос, поэтому ставлю его здесь
  • 1
    обратите внимание также, что ваш цикл проверки в пределах диапазона не работает, так как он не записывает каждое значение канала обратно в список new_pixel . Рассмотрим new_pixel= [max(min(channel, 255), 0) for channel in new_pixel] . Вероятно, более эффективным способом «облегчения» было бы уменьшение разницы между значением канала и 255, а не умножение самого значения канала, поскольку оно будет насыщаться быстрее. Еще лучше было бы преобразовать в цветовое пространство HSL, изменить значение Lightness, а затем преобразовать обратно. Бонусные баллы за размышления о гамме.
Показать ещё 2 комментария
Теги:
python-imaging-library

1 ответ

1
Лучший ответ

Это проблема целочисленного деления в выражении (extent/100). Чтобы исправить это, вы можете:

используйте литерал с плавающей запятой

extent/100.0

Удобно, если термин является литералом.

преобразует либо числитель, либо знаменатель в float

float(extent)/a_hundred

Если ни один из слов не является литералом.

убедитесь, что / floating- деление точки

from __future__ import division

Вставьте это в начале исходного файла, как и все инструкции __future__.

вызывать python с помощью -Qnew

python -Qnew

Если используется python2, в противном случае

использовать python3:)

Во всех случаях // остается целочисленным делением.

  • 0
    Спасибо за это. Поскольку это универсальный проект, мы должны использовать Python 2.5 (а не 2.7 по какой-то глупой причине). Я использовал метод с плавающей запятой, и это сработало.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню