ответ

5

Вот 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 выглядит следующим образом:

enter image description here

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

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

Result:

+1

Ответ уже довольно хорошо, но я думаю, что это было бы еще более полезным и для других, если бы более expalantion данного фрагмента кода. В основном, как он достигает, чего он добивается? – Trilarion

+0

Я согласен с @Trilarion. Я заинтригован тем, как вы получили это, чтобы работать. Я не разработчик iOS, и поэтому то, что вы написали выше, не имеет для меня никакого смысла. Я хотел бы знать, каковы основные шаги к вашему алгоритму. – rayryeng

2

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

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

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

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

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

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

Смежные вопросы