Как добиться адаптивного порогового фильтра с цветом

Я ищу алгоритм, похожий на адаптивный порог, но он сохраняет цвет. Я пытаюсь сделать снимок вот так:

исходное изображение

И сделайте так, чтобы это выглядело так:

обработанное изображение

Если это имеет значение, я работаю в IOS.

2 ответа

Решение

Вот CIKernel, который хорошо работает на вашем образце

kernel vec4 coreImageKernel (sampler i)
{
    vec2 dc = destCoord();

    // center pixel color
    vec4 c = unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,0.0))));

    // for a whiteboard, the max of a neighborhood is likely to be the color 
    // of the whiteboard
    vec4 cmax = c;
    cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(10.0,0.0)))), cmax);
    cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(-10.0,0.0)))), cmax);
    cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,10.0)))), cmax);
    cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,-10.0)))), cmax);

    // normalize the center color according to the whiteboard color
    vec4 r = c / cmax;
    return premultiply(r);
}

Так как же это работает? Итак, первая часть ядра, часть, которая вычисляет cmax, вычисляет локальный цвет доски. Это сложная часть. По сути, он определяет (приблизительно) цвет, которым будет доска, если на ней нет отметок. Для этого ядро ​​делает три основных предположения:

  1. цвет доски не сильно отличается
  2. маркеры вычитают из цвета доски и
  3. что для каждого пикселя, он или соседний пиксель (10, N,S,E или W) не имеют маркировки. По сути, ядро ​​предполагает, что отмеченные линии тоньше 10 пикселей, хотя эту константу можно настроить)

Вот как выглядит вывод cmax:

После аппроксимации цвета локальной доски это просто вопрос деления текущего пикселя на локальный фон. Это похоже на то, как цветовой оттенок удаляется из изображения.

Этот алгоритм аналогичен примеру удаления дымки из представления основного изображения WWDC13. В этом примере локальный мин вычитается, чтобы сделать черных чернее. В этом случае местный максимум делится для получения белого цвета.

Результат:

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

Поэтому простой подход приведет к следующему рабочему процессу:

  • Изображение с красным, зеленым, синим значением
  • Создайте серое изображение, добавив красный + зеленый + синий
  • Создайте маску серого масштабированного изображения по локальному адаптивному порогу на изображении серой шкалы
  • Применить маску к исходному изображению с красными, зелеными, синими значениями

В качестве альтернативы может быть:

  • Изображение с красным, зеленым, синим значением
  • Создайте три маски для изображения, используя только красные (или зеленые или синие соответственно) значения
  • Объедините все три маски (логические и), чтобы получить одну маску
  • Применить маску к исходному изображению со значениями красного, зеленого и синего

Эти два способа могут быть не идеальными, но, вероятно, уже работают для большого числа случаев, включая пример в вопросе.

Другие вопросы по тегам