Билинейная интерполяция для увеличения растровых изображений - PullRequest
7 голосов
/ 10 января 2012

Я студент, и мне было поручено оптимизировать билинейную интерполяцию изображений, используя параллелизм из CUDA.

Изображение предоставляется в 24-битном формате .bmp.У меня уже есть считыватель для .bmp, и я сохранил пиксели в массиве.

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

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

Ответы [ 3 ]

37 голосов
/ 11 января 2012

Самый простой способ понять билинейную интерполяцию - это понять линейную интерполяцию в 1D.

Эта первая цифра должна дать вам воспоминания о математике средней школы. Для некоторого местоположения a , в котором мы хотим знать f (a) , мы берем соседние "известные" значения и помещаем линию между ними.

Linear interpolation in 1D.

Итак, мы просто использовали старые уравнения средней школы y = mx + b и y-y1 = m (x-x1). Ничего особенного.

Мы в основном переносим эту концепцию в 2-D, чтобы получить билинейную интерполяцию. Мы можем решить проблему нахождения f (a, b) для любого a, b , выполнив три интерполяции. Внимательно изучите следующую фигуру. Не пугайтесь всех ярлыков. Это на самом деле довольно просто.

Bilinear interpolation as three 1D interpolations.

Для билинейной интерполяции мы снова используем соседние точки. Сейчас их четыре, так как мы в 2D. Хитрость заключается в том, чтобы атаковать проблему по одному измерению за раз.

Мы проецируем наши (a, b) в стороны и сначала вычисляем две (одномерные!) Интерполяционные линии.

  • f (a, y j ) где y j поддерживается постоянной
  • f (a, y j + 1 ) , где y j + 1 поддерживается постоянным.

Теперь есть только один последний шаг. Вы берете две вычисленные вами точки: f (a, y j ) и f (a, y j + 1 ) , и провести линию между ними. Это синий, идущий слева направо на диаграмме, проходящий через f (a, b) . Интерполяция по этой последней строке дает вам окончательный ответ.

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

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

9 голосов
/ 10 января 2012

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

См. Изображения в ИЗМЕНЕНИЕ ИЗОБРАЖЕНИЯПРИМЕР .

Формула f(x,y)=... в этой статье в Википедии дает вам метод для вычисления цвета f вставленного пикселя:

enter image description here

Для каждого вставленного пикселя вы комбинируете цвета 4 исходных пикселей (Q11, Q12, Q21, Q22), окружающих его.Комбинация зависит от расстояния между вставленным пикселем и окружающими исходными пикселями, чем ближе к одному из них, тем ближе их цвета:

enter image description here

Исходные пикселипоказано как красный.Вставленный пиксель отображается зеленым цветом.

В этом и заключается идея.

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

3 голосов
/ 10 января 2012

Не зацикливайтесь на том факте, что 2D-массивы в C на самом деле являются 1D-массивами. Это деталь реализации. Математически вам все равно нужно думать в терминах двумерных массивов.

Подумайте о линейной интерполяции в одномерном массиве. Вы знаете значение в 0, 1, 2, 3, ... Теперь предположим, что я прошу вас ввести значение в 1.4. Вы бы дали мне взвешенное сочетание значений в 1 и 2: (1 - 0.4)*A[1] + 0.4*A[2]. Просто, правда?

Теперь вам нужно расширить до 2D. Нет проблем. 2D-интерполяция может быть разложена на две 1D-интерполяции, по оси x и затем по оси y. Скажи, что хочешь (1.4, 2.8). Получите одномерные интерполяции между (1, 2)<->(2,2) и (1,3)<->(2,3). Это ваш шаг по оси X. Теперь 1D интерполировать между ними с соответствующими весами для y = 2.8.

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

...