GIMP: «Сложный» порог

В данной статье будет изложено проектирование «сложного» порога в 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 и лишь позднее, по мере усложнения, была перенесена в Си. Для того, чтобы не возникало вопросов «что за принципы?» приведу ссылки на предыдущие статьи, в которых эти принципы изложены:

  • GIMP: префильтрация перед порогом

  • 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» — исходное изображение

Исходное изображение
Исходное изображение «Лена» (I)

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

«Гауссово размывание» с радиусами 10×10 (B)

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

«Извлечение зерна» (D)

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

«Гауссово размывание» разности с радиусами 10×10 (S)

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

«Извлечение зерна» (N)

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

«Извлечение зерна» (F)

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

Микшированное изображение (M)
Микшированное изображение (M)

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

Результат порога
Результат порога «Grain» (T)

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

© Habrahabr.ru