Пишем скрипты для GIMP 2.x. Практичный пример – коррекция цвета (Scheme, Python).

от
Работа с графикой    python

В прошлой статье я показал основы создания скриптов для GIMP 2.x.

Теперь сделаем практичную вещь. Под спойлером – о том, как мне пришла в голову идея этого скрипта.

Открыть спойлер

Принцип действия
Оказывается, многие «мыльницы» делают на фото слишком много синего цвета. И, как по мне, немного больше, чем нужно, зеленого.

От этого создается ощущение, что картинка теряет резкость и кажется замыленной. Кстати, подобным грешат многие картинки из сети.

Стоило мне минут 20-25 поковыряться с в Gimp’е кривыми, насыщенностью-освещенностью и прибавить буквально 2-6 единиц контраста – фото будто подменили! Оно перестало быть чем-то невзрачным, на что я бы в лучшем случае подумал «да ну, таких картинок в кучу можно наделать». Напротив – ожило, заиграло красками.

  img1.jpg
  img3.jpg
  img2.jpg

Было дело, я долго ковырялся с каждым фото, подбирая цветовой баланс к каждому индивидуально. А потом делал сестре презентации в Power Point. Изображений с интернета было много, и к каждому индивидуально подходить я не мог.

Но заметил, если ко всем применять одинаковые настройки в последовательности:

1. Отрулить синего и чуть зеленого в кривых
2. Добавить насыщенности
3. Добавить до 4-6 единиц контраста

Такая обработка подойдет для большинства изображений. А чтоб не ковыряться с ними вручную – автоматизировал алгоритм!

Сначала я записал это на Script-Fu
  1. (define (script-fu-fix-color image)
  2.  
  3.  
  4.         (let*
  5.         (
  6.  
  7.  
  8.             (image_copy (car (gimp-image-duplicate image)))
  9.             (layer (car (gimp-image-get-active-layer image_copy)))
  10.         )
  11.  
  12.         (gimp-image-undo-disable image)
  13.  
  14.     (gimp-curves-spline layer 1 6 #(0 0 128 128 255 255))
  15.     (gimp-curves-spline layer 2 6 #(0 0 128 125 255 255))
  16.     (gimp-curves-spline layer 3 6 #(0 0 140 111 255 255))
  17.  
  18.     (gimp-hue-saturation layer 0 0 0 22)
  19.     (gimp-brightness-contrast layer 0 4)
  20.  
  21.         (gimp-image-undo-enable image)
  22.  
  23. (gimp-display-new image_copy)
  24.         )
  25. )
  26.  
  27. (script-fu-register
  28.  
  29. "script-fu-fix-color"  
  30. "Коррекция цвета"
  31. "Коррекция цвета"
  32. "M_N"
  33. "bY M_N"
  34. "09-02-2016"
  35. "RGB* INDEXED*"
  36.  
  37.   SF-IMAGE       "IMG" 0
  38.  
  39. )
  40.  
  41. (script-fu-menu-register
  42.  
  43. "script-fu-fix-color"
  44. "<Image>/Filters/Улучшение фото"
  45. )

Как видите, все очень просто (если все же трудно – прочтите статьи по ссылкам в начале ^^ ). Самым сложным было разобраться в работе функций. Я расскажу, как ориентироваться в них.

1. Как я эти функции нашел?

Сначала все просто – ищете нужный инструмент в Gimp’е. Пусть это будут кривые. По-английски слово «кривые» читается как «curves». Заходим в просмотрщик функций через консоль, в строке поиска вводим английское название инструмента.

   curves.jpg

Видим – выдает 2 функции. Смотрим описание «gimp-curves-explicit» (переводим гугле или яндексе, если надо), смотрим на список ее аргументов. Ага, что-то не то. Нам не подходит, смотрим следующую: «gimp-curves-spline».

Отлично! То, что надо. Последний аргумент – массив, в котором заключены координаты точек для построения кривых.

Аналогично – яркость-контраст. Вводим в строку поиска слова «яркость» и «контраст» по-английски (brightness или contrast) и получаем единственный результат: «gimp-brightness-contrast».

2. Как же эти функции работают?

С яркостью-контрастом и освещенностью-насыщенностью я разобрался сразу.

  1. (gimp-brightness-contrast layer 0 4)

1-й аргумент – ID активного слоя
2-й аргумент – яркость
3-й аргумент – контраст

  1. (gimp-hue-saturation layer 0 0 0 22)

1-й аргумент – ID активного слоя
4-й аргумент – освещенность
5-й аргумент – насыщенность

А кривые заставили меня поломать голову. Посмотрим на код, работающий с ними:

  1. (gimp-curves-spline layer 1 6 #(0 0 128 128 255 255))
  2. (gimp-curves-spline layer 2 6 #(0 0 128 125 255 255))
  3. (gimp-curves-spline layer 3 6 #(0 0 140 111 255 255))

1-й аргумент – режим работы функции. Цифра 1 сообщает ей, что надо работать с красным цветом, 2 – с зеленым, и 3 с синим. Можно работать с общим фоном (0, одна кривая изменяет сразу 3 цвета), с альфа-каналом (4) и обработать все цвета в одну строку (5). Но нам туда лезть не нужно.

3-й аргумент – массив с координатами для построения кривых.

Да, именно массив (или вектор, кому как нравится), а не список, объявляющийся как ‘().

Как функция строит кривые? 2-й аргумент указывает число элементов массива (минимум 4, но нам надо минимум 6, чтобы построить полноценную кривую).

Первые 2 элемента массива – начало линии.
Последние 2 элемента – конец.
2 элемента посередине – точка на линии, которая и делает из нее кривую.

Первой записывается координата по X, второй координата по Y. Наглядно на скрине:

   curves2.jpg

Думаю, вопрос с работой этой функции в данном скрипте исчерпан.

Последовательность обработки
Для наглядности давайте посмотрим на сам процесс обработки (впрочем, это можно глянуть и самому, убрав функции gimp-image-undo-disable - gimp-image-undo-enable).

Возьмем в качестве оригинала мое первое из сохранившихся фото, сделанное на мобилку Sony Ericsson k300.

  obr1.jpg
 
Пропустим его через кривые:

  obr2.jpg

Картинка стала теплее, но… Все равно как-то бледно выглядит. Добавим насыщенности:

  obr3.jpg

Появились цвета! Теперь серо и уныло фото не выглядит. Правда, эти цвета будто водой разбавлены – не хватает контраста. Исправляем:

  obr4.jpg

Совсем другое дело.

Результаты обработки
Возьмем фото одуванчика ))

   sample1.jpg

Первый кадр слева – оригинал. Интересно, но… Что-то не то. Кадр посередине – обработка нашей функцией. Вот, уже интересней. Хотя я бы еще покрутил зеленый цвет, ибо он тут в изобилии.

Третий кадр слева – повторная обработка фото. Казалось бы, и цвета, и контраст есть, но всего в переизбытке. Слишком много.

Теперь фото листа клубники на закате.

  sample2.jpg

1-й вариант (слева направо) не примечателен. Обычная макросъемка, таких много. 2-й уже интереснее. 3-й – еще интереснее, хотя заметен перебор с контрастом.

Фото жука.

  sample4.jpg

Первый вариант интересен, однако по сравнению со вторым он блекнет. А 3-й – явный перебор по всем параметрам.

Совершенствуем функцию и переходим на Python
Конечно, фильтр работает и делает свое дело на твердую четверку. Однако выше я говорил, что наиболее эффективно искать подход к каждому изображению индивидуально.

Поэтому я решил усовершенствовать функцию, сделав возможность тонкой подстройки параметров. Чтобы перед обработкой можно было быстро подкрутить то или иное значение под картинку.

Это делается просто – создаем в окне нужный интерфейс, и передает с него параметры в нужные функции. Однако поковыряв Scheme (он же разновидность Lisp) я обнаружил, что Python все же удобнее, и информации по нему в сети валом.

Python в Gimp 2.8
Да, именно в этой версии и появляется какая-никакая его поддержка по умолчанию.

Скачать Gimp 2.8 можно на официальном сайте – инсталлятор весит около 90 мегабайт.

И один нюанс. Качайте либо с отключенным антивирусником, либо через Download Master, т.к. антивирус может порезать закачку.

Открываем Фильтры => Python-Fu => консоль. Видим такое:

   python-in-gimp-2-8.JPG

Печатать можно прямо в окне, никаких полей для ввода нет. Там же и выводится результат исполнения выражений.

Кнопка «просмотр» открывает окно со списком функций. Обратите внимание – названия функций в списке такие, как в Script-Fu. Но как только вы скопируете их, в консоли они будут с синтаксисом Python’а. Например, находим «file-jpeg-load». Нажимаем «применить», и в консоли уже видим «image = pdb.file_jpeg_load(filename, raw_filename)».

Также почему-то они используют Python 2.7, тогда как есть уже версия 3.5. А между ними есть небольшие различия в синтаксисе.

Особенности Python
Я не буду рассказывать основы этого языка, за меня это уже сделали.

Вот – хороший самоучитель, но для версий выше 3.0.

Я лишь расскажу кое-какие важные особенности.

Hello World

Выглядит так:

  1. print ("Привет")

Конец строки – ее окончание. Т.е. там ничего ставить не надо.

Функции, циклы и т.п.

  1. n = 0
  2. while (n < 10):
  3.     n=n+1
  4.     print n

Простейший цикл, будет выполняться пока «n» не станет больше 10.

  1. def myfunc():
  2.     print 2*2

Простейшая функция.

Как видите, тело функции-цикла-условия не заключается ни в какие скобочки. Оно начинается сразу после строки с его объявлением и двоеточием. А отделяется от остального кода знаком табуляции (кнопка Tab). Т.е. так не работает:

  1. while (n < 10):
  2. n=n+1
  3. print n

Продвинутый вариант скрипта на Python
Вот – весь код:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. #^^ Без этого не работает
  5.  
  6. from gimpfu import *
  7.  
  8. def shift_y(x,y):
  9.     return y + (x - 128)
  10.  
  11. def fix_color_pro(image, rx, ry, gx, gy, bx, by, light, color, brightness, contrast):
  12.     image_copy=pdb.gimp_image_duplicate(image)
  13.     pdb.gimp_image_undo_group_start(image_copy)
  14.     layer=pdb.gimp_image_get_active_layer(image_copy)
  15.  
  16.     pdb.gimp_curves_spline(layer, 1, 6, [0, 0, rx, shift_y(rx, ry), 255, 255])
  17.     pdb.gimp_curves_spline(layer, 2, 6, [0, 0, gx, shift_y(gx, gy), 255, 255])
  18.     pdb.gimp_curves_spline(layer, 3, 6, [0, 0, bx, shift_y(bx, by), 255, 255])
  19.  
  20.     pdb.gimp_hue_saturation(layer, 0, 0, light, color)
  21.     pdb.gimp_brightness_contrast(layer, brightness, contrast)
  22.  
  23.     pdb.gimp_image_undo_group_end(image_copy)
  24.  
  25.     pdb.gimp_display_new(image_copy)
  26.  
  27. register(
  28.         "python-fu-fix-color-pro",
  29.         "Продвинутая коррекция цвета",
  30.         "Исправляем баланс цветов на картинке",
  31.         "M_N",
  32.         "bY M_N",
  33.         "10-02-2016",
  34.         "Продвинутая коррекция цвета bY M_N",
  35.         "*",
  36.           [
  37.               (PF_IMAGE, "image", "Исходное изображение", None),
  38.  
  39.               (PF_SLIDER, "rx", "Красный X", 128, (98,134,1)),
  40.               (PF_SLIDER, "rx", "Красный Y", 128, (110,134,1)),
  41.               (PF_SLIDER, "gx", "Зеленый X", 128, (100,160,1)),
  42.               (PF_SLIDER, "gy", "Зеленый Y", 125, (121,130,1)),
  43.               (PF_SLIDER, "bx", "Синий X", 140, (45,185,1)),
  44.               (PF_SLIDER, "by", "Синий Y", 111, (100,127,1)),
  45.  
  46.               (PF_SLIDER, "light", "Освещенность", 0, (-10,10,1)),
  47.               (PF_SLIDER, "color", "Насыщенность", 22, (18,34,1)),
  48.  
  49.               (PF_SLIDER, "brightness", "Яркость", 0, (-2,3,1)),
  50.               (PF_SLIDER, "contrast", "Контраст", 4, (0,10,1)),
  51.  
  52.           ],
  53.           [],
  54.           fix_color_pro, menu="<Image>/Filters/Улучшение фото/")
  55.  
  56. # Пуск!
  57. main()

Очевидно, скрипт добавляет окно с параметрами.

Что бросается в глаза сразу?
В отличие от Scheme, запускает работу скрипта функция main() в конце кода. А в самом начале два комментария:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-

Без них тоже ничего не запустятся – они передают интерпретатору нужную конфигурацию для работы. В скриптах на Script-Fu этого не было.

Окно скрипта
У нас выглядит оно так:

  window-script.jpg

Механизм регистрации скрипта почти такой, как в Script-Fu:

  1. register(
  2.         "python-fu-fix-color-pro",
  3.         "Продвинутая коррекция цвета",
  4.         "Исправляем баланс цветов на картинке",
  5.         "M_N",
  6.         "bY M_N",
  7.         "10-02-2016",
  8.         "Продвинутая коррекция цвета bY M_N",
  9.         "*",
  10.           [
  11.               (PF_IMAGE, "image", "Исходное изображение", None),
  12.  
  13.               (PF_SLIDER, "rx", "Красный X", 128, (98,134,1)),
  14.               (PF_SLIDER, "rx", "Красный Y", 128, (110,134,1)),
  15.               (PF_SLIDER, "gx", "Зеленый X", 128, (100,160,1)),
  16.               (PF_SLIDER, "gy", "Зеленый Y", 125, (121,130,1)),
  17.               (PF_SLIDER, "bx", "Синий X", 140, (45,185,1)),
  18.               (PF_SLIDER, "by", "Синий Y", 111, (100,127,1)),
  19.  
  20.               (PF_SLIDER, "light", "Освещенность", 0, (-10,10,1)),
  21.               (PF_SLIDER, "color", "Насыщенность", 22, (18,34,1)),
  22.  
  23.               (PF_SLIDER, "brightness", "Яркость", 0, (4,4,1)),
  24.               (PF_SLIDER, "contrast", "Контраст", 4, (0,10,1)),
  25.  
  26.           ],
  27.           [],
  28.           fix_color_pro, menu="<Image>/Filters/Улучшение фото/")

Только все умещено в одну функцию. Элементы окна содержатся в списке (в квадратных скобках [] ). В целом они записываются так же, как в Script-Fu.

Однако сами элементы кое-где между собой различаются. Например, за создание слайдера и спиннера там использовался один SF-ADJUSTMENT. Тут же для слайдера есть PF-SLIDER, а для спиннера PF-SPINNER.

Их входящие аргументы идентичны. Например, возьмем:

  1. (PF_SLIDER, "contrast", "Контраст", 4, (0,10,1))

1-й аргумент – имя переменной, в которую запишется значение параметра.
2-й агрумент – название элемента в окне.
3-й аргумент – значение по умолчанию.
4-й аргумент – минимальное, максимальное значения и шаг его изменения.

Регистрируется функция этой строкой:

  
  1. fix_color_pro, menu="<Image>/Filters/Улучшение фото/"

1-й параметр – имя регистрируемой функции.
2-й параметр – путь к скрипту в меню.

Передача параметров с окна
Как вы заметили, первый аргумент элемента окна – имя переменной, в которую с него поступят данные.

Теперь посмотрим на объявление регистрируемой нами функции:

  1. def fix_color_pro(image, rx, ry, gx, gy, bx, by, light, color, brightness, contrast):

Все входящие параметры должны полностью соответствовать заданным в окне. Т.е. если мы зарегистрировали в окне элементы image, rx, ry, gx, gy, bx, by, light, color, brightness, contrast – именно они и должны входить в функцию. Если мы какой-то уберем, или какой-то добавим, скрипт работать не будет.

Регистрация скрипта в базе данных Gimp’а
1. Создаем текстовый файл, переименовываем разрешение из .txt в .py.
2. Записываем в него код.
3. Копируем файл в C:\Users\[ИМЯ ПОЛЬЗОВАТЕЛЯ]\.gimp-2.8\plug-ins. Да, именно в папку с плагинами – Gimp скрипты на питоне считает плагинами.
4. Запускаем Gimp. Если все работает, скрипт найдете в меню по прописанному пути.

Готово!

Осваиваемся с тонкой настройкой скрипта

Тут вопросы могут возникнуть только по кривым. Я расскажу, как они работают.

Значение по Y – уменьшает/увеличивает количество нужного цвета в изображении.

Значение по X – перемещает акцент от светлых до темных участков изображения. Например, если мы по X поставили точку где-то на 40-60, то по Y мы будем изменять количество цвета преимущественно на темных участках.

Если точку поставим по X на 160-180 – наоборот. По Y будем изменять количество цвета преимущественно на светлых участках.

Функция shift_y
Ее роль такова. Например, нам надо изменить со скрипта значение X на 175, а Y оставить на 110. Это – не то же самое, когда X 128, а Y 110.

Вот график, примерно показывающий 1-й случай (175, 110):

   grafik2.jpg

Вот – 2-й (128, 110):

   grafik1.jpg

Видите, куда точка над кривой уходит от диагонали? А именно относительно нее Gimp и берет параметры с кривых. Значит, нам нужно рассчитать смещение координаты Y так, чтобы при любом значении X расстояние точки до диагонали оставалось неизменным.

А что, самим в уме его считать?

  1. def shift_y(x,y):
  2.     return y + (x - 128)

Что мы здесь делаем?

1. Принимаем значение 128 как 0. В кривых это так и есть.
2. Вычисляем расстояние X до нуля.
3. Добавляем получившееся число к Y.

Теперь, какое бы значение мы не задали X, расстояние точки до кривой останется неизменно:

   grafik3.jpg

Крутим тонкую настройку
Давайте возьмем уже известное мое фото с SE k300, и попробуем при его обработке отодвинуть X на 180:

   alt1.jpg

Хоть цвета и стали сочнее и насыщенней, атмосфера мрачности, которая бывает при пасмурной погоде или при позднем закате, не исчезла.

Отодвинем X до 60.

   alt2.jpg

Тут – наоборот, атмосфера больше подходит для яркого солнечного дня.

Готово! Основную идею я изложил.
Что мы сделали?

Воплотили в код кое-какой алгоритм коррекции цвета.
Разобрали глубже тему создания скриптов на Gimp 2.x.
Разобрали особенности работы Gimp’а с Python’ом.

А у вас есть свои идеи обработки изображений? Обсудим в комментариях?
  • +10
  • views 9919