Как работает нерезкая маска? - PullRequest
11 голосов
/ 30 мая 2010

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

Ответы [ 5 ]

28 голосов
/ 30 мая 2010

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

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

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

    Алгоритм выглядит следующим образом: посмотрите на пиксель из нерезкой маски и выясните его яркость (яркость). Если яркость равна 100%, используйте значение из высококонтрастного изображения для этого пикселя. Если это 0%, используйте значение из исходного изображения для этого пикселя. Если это где-то посередине, смешайте значения двух пикселей, используя некоторое взвешивание. Необязательно, изменяйте значение пикселя только в том случае, если оно изменяется более чем на определенную величину (это слайдер Threshold в большинстве диалоговых окон 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;
}

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

Ссылки

10 голосов
/ 30 мая 2010

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

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

Тогда его эффект в области пространственных частот равен:

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

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

5 голосов
/ 30 мая 2010

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

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

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

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

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

4 голосов
/ 30 мая 2010

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

blurred_image = blur(input_image)
output_image = input_image - blurred_image * weight
2 голосов
/ 28 февраля 2015

Рассмотрим приведенный ниже код, который берется во входное изображение IMG.

IMGblur = blur(IMG) // get all the low frequency pixels 
temp = IMG - IMGblur // all the low frequency pixels will be 0 
IMGsharp = IMG + k(temp) // k is in [0.3,0.7]
// in this final result , all low frequency pixels of IMGsharp is same as IMG, 
// but all high frequency signals of IMGsharp is (1+k)times higher than IMG 

Надеюсь, это поможет!

Скоро Чи Лунг,

Университет Торонто

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...