В данной статье будет изложено проектирование "сложного" порога в GIMP. "Сложность" заключается в том, что к порогу изначально предъявлялись строго определённые характеристики.
Здесь уже никак не обойтись без указания продукта, для которого проектировался порог, и причин таких строгих требований.
История вопроса.
Объектом или целью данного проектирования стал ScanTailor-Experimental (STEX). Этот продукт предназначен для обработки сканированных изображений и содержит множество порогов, как классических, так и основанных на префильтрации, а также один гибридный порог.
Все эти пороги имеют достоинства и недостатки. Но причиной данного проектирования стали два конкретных порога: порог с префильтром "EdgeDiv" и гибридный порог Grad (aka "Gradient Snip"). А говоря точнее причиной стали недостатки этих двух порогов.
Необходимо сделать уточняющее замечание: оба указанных порога, в отличии от классических (Niblack, Sauvola, Wolf), рассчитаны на работу с малыми радиусами фильтрации (3 - 20) и имеют возрастающий коэффициент от глобального порога к "локальному" (коэффициент определяет "локальную" долю в результате порога).
Что же не так с этими порогами?
Порог "EdgeDiv" является комбинацией префильтра "EdgeDiv" и порога Оцу/оптимального. В свою очередь префильтр "EdgeDiv" состоит из двух компонент: "EdgePlus" и "BlurDiv". Это не очень то простой для понимания и в тоже время жёсткий префильтр, оказывающий сильное воздействие на исходное изображение. Этот порог хорошо зарекомендовал себя не только у пользователей STEX, но и у пользователей STA (ScanTailor-Advanced), и у пользователей STU (ScanTailor-Universal). Во всех отзывах отмечается хорошая отрисовка всех букв без ужирнения, в отличии от Wolf или Sauvola. Это связано не только с особенностями префильтра, но и с малыми радиусами фильтрации. Так в чём недостаток этого порога? На него оказывает сильное влияние неравномерность освещения. Да, в STEX есть сильный фильтр "Выровнять освещение", но не на каждом материале ("Смешанном", например) его можно применить. Это определённая "проблема".
Порог "Grad" (aka "Gradient Snip") - единственный удачный известный мне гибридный порог, пороговая карта которого формируется микшированием глобального значения порога и локального. Этот порог не получил таких же откликов от пользователей, как "EdgeDiv", и понятно почему. Этот порог хоть и работает на тех же радиусах фильтрации, что и "EdgeDiv", но делает штрихи жирнее. Да, штрихи получаются менее жирными, чем у Wolf и Sauvola, (сказывается разность радиусов фильтрации), но всё-равно толще, чем "EdgeDiv". Так зачем же он тогда нужен? А этот порог в рабочем диапазоне коэффициентов (0.5 - 1.0) практически вчистую игнорирует неравномерность освещения.
Отсюда и возникла задача проектирования нового порога и требования к нему. Требуется спроектировать порог, дающий толщину штрихов, схожую с "EdgeDiv", но менее чувствительный к неравномерности освещения. При этом данный порог должен работать на тех же радиусах, что и "EdgeDiv" и "Grad". Естественно, такой порог будет иметь свои недостатки (что и подтвердилось после реализации), но это даёт пользователю манёвр менять порог, без изменения радиуса фильтрации и коэффициента.
Проектирование порога "Grain" ("Зерно").
Данный порог проектировался в GIMP, основываясь на принципах префильтрации и опыте разработки порога "EdgeDiv", разработка которого также начиналась в GIMP и лишь позднее, по мере усложнения, была перенесена в Си. Для того, чтобы не возникало вопросов "что за принципы?" приведу ссылки на предыдущие статьи, в которых эти принципы изложены:
Сам процесс проектирования разжёвывать не буду, для его понимания необходимо знать свойства порогов "EdgeDiv" и "Grad", а это выходит за рамки данной статьи. Приведу результат проектирования и построчно продемонстрирую его работу на конкретном изображении.
Порог "Grain":
I
B = BLUR(I,r)
D = GRAIN(I,B)
S = BLUR(D,r)
N = GRAIN(S,D)
F = GRAIN(D,N)
M = k * F + (1 - k) * I
T = OTSU(M)
Далее каждую строчку буду демонстрировать конкретным изображением "Лена".
"I" - исходное изображение

"B = BLUR(I,r)" - размытое изображение (копия исходного слоя). Для размытия изображения использую "Гауссово размывание" с радиусами 10 и 10.

"D = GRAIN(I,B)" - наложение "Извлечение зерна" размытого изображения и исходного (разность двух слоёв).

"S = BLUR(D,r)" - размытое изображение (копия разности). Для размытия изображения использую "Гауссово размывание" с радиусами 10 и 10.

"N = GRAIN(S,D)" - наложение "Извлечение зерна" разности без размытия и размытой разности (хвостовое изображение).

"F = GRAIN(D,N)" - наложение "Извлечение зерна" хвостового изображения и разности без размытия (фильтрованное изображение).

"M = k F + (1 - k) I" - микширование фильтрованного слоя (установка прозрачности 75%, что соответствует коэффициенту 0.75) и исходного изображения.

"T = OTSU(M)" - применение "Порога" с автоматическим определением значения (кнопка "Авто").

Данная демонстрация показывает, что задачи, поставленные при проектировании выполнены. При этом выявились и недостатки. Префильтрация оказалась сильнее, чем рассчитывалось изначально, но только такая префильтрация обеспечила выполнение требований к новому порогу. Но не бывает ничего "за так". В результате порог получился гораздо менее предсказуемым, чем "EdgeDiv" и "Grad", и требует гораздо большей аккуратности при выборе параметров.