Как нерезкая маска работает?

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

11
задан Bob Aman 30 May 2010 в 10:03
поделиться

4 ответа

Я тоже не знал, как это работает, но наткнулся на пару действительно хороших страниц, чтобы понять это. Обычно это выглядит так:

  1. Что противоположно более резкому изображению? Расплывчатый. Мы знаем, как размыть изображение. Дублируйте исходное изображение и выполните размытие по Гауссу. Это ползунок Радиус в большинстве диалогов USM.
  2. Что ж, если мы уберем размытость, у нас останутся высококонтрастные части! Подумайте об этом: если вы размываете небо, оно все равно выглядит как небо. Вычтите пиксели, и вы получите небо - небо = 0. Если вы размываете логотип Coke, вы получите размытый логотип Coke. Вычтите это, и у вас останутся края. Итак, какая разница
  3. Что же делает вещи более резкими? Контраст.Снова продублируйте исходное изображение и увеличьте контраст. Степень увеличения контрастности - это ползунок Amount или Intensity в большинстве диалоговых окон USM.
  4. Наконец собрал все воедино. На данный момент у вас есть три вещи:

    1. Высококонтрастная версия вашего исходного изображения
    2. Разница между размытым изображением и вашим оригиналом (этот слой в основном черный). Этот слой представляет собой маску нерезкости
    3. Исходный

    Алгоритм выглядит следующим образом: посмотрите на пиксель из маски нерезкости и узнайте его яркость (яркость). Если яркость равна 100%, используйте значение из высококонтрастного изображения для этого пикселя. Если это 0%, используйте значение из исходного изображения для этого пикселя. Если это где-то посередине, смешайте значения двух пикселей, используя некоторое взвешивание. При желании можно изменять значение пикселя, только если оно изменяется более чем на определенную величину (это ползунок Порог в большинстве диалогов USM).

Сложите все вместе, и вы получите свой образ!

Вот какой-то псевдокод:

color[][] usm(color[][] original, int radius, int amountPercent, int threshold) {
  // copy original for our return value
  color[][] retval = copy(original);

  // create the blurred copy
  color[][] blurred = gaussianBlur(original, radius);

  // subtract blurred from original, pixel-by-pixel to make unsharp mask
  color[][] unsharpMask = difference(original, blurred);

  color[][] highContrast = increaseContrast(original, amountPercent);

  // assuming row-major ordering
  for(int row = 0; row < original.length; row++) {
    for(int col = 0; col < original[row].length; col++) {
       color origColor = original[row][col];
       color contrastColor = highContrast[row][col];

       color difference = contrastColor - origColor;
       float percent = luminanceAsPercent(unsharpMask[row][col]);

       color delta = difference * percent;

       if(abs(delta) > threshold)
         retval[row][col] += delta;
    }
  }

  return retval;
}

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

Ссылки

28
ответ дан 3 December 2019 в 01:00
поделиться

Нерезкость обычно реализуется как ядро ​​свертки, которое обнаруживает края. Результат этой свертки добавляется обратно к исходному изображению для увеличения контрастности краев, что добавляет иллюзию дополнительной «резкости».

Точное используемое ядро ​​сильно различается от человека к человеку и от приложения к приложению. Большинство из них имеют такой общий формат:

    -1 -1 -1
g = -1  8 -1
    -1 -1 -1

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

Для входного изображения I выход определяется как: out = I + c (I * g) , где * - оператор двумерной свертки, а c - некоторая константа масштабирования, обычно выше 0,5 и меньше 1 , поэтому вы не перегружаете больше каналов, чем необходимо.

5
ответ дан 3 December 2019 в 01:00
поделиться

Unsharp Mask работает путем создания размытой версии изображения с помощью фильтра размытия Гаусса, а затем вычитания ее из исходного изображения (с применением некоторого значения веса), т. е.

blurred_image = blur(input_image)
output_image = input_image - blurred_image * weight
4
ответ дан 3 December 2019 в 01:00
поделиться

Ключевым является идея пространственной частоты . Гауссовский фильтр пропускает только низкие пространственные частоты, поэтому, если вы сделаете что-то вроде:

2 * (исходное изображение) - (гауссово фильтрованное изображение)

, то его эффект в области пространственных частот будет следующим:

(2 * все частоты) - (низкие частоты) = (2 * высокие частоты) + (1 * низкие частоты).

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

10
ответ дан 3 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: