Алгоритм интерполяции ближайшего соседа в MATLAB - PullRequest
20 голосов
/ 11 октября 2009

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

Вот что я пытался увеличить для входного изображения в 2 раза:

function output = nearest(input)
[x,y]=size(input);
output = repmat(uint8(0),x*2,y*2);
[newwidth,newheight]=size(output);
for i=1:y
    for j=1:x
        xloc = round ((j * (newwidth+1)) / (x+1));
        yloc = round ((i * (newheight+1)) / (y+1));
        output(xloc,yloc) = input(j,i);
    end
end

Вот вывод после Отметить предложение alt text

Ответы [ 4 ]

20 голосов
/ 12 октября 2009

Этот ответ более объяснительный, чем попытка быть кратким и эффективным. Я думаю, что решение gnovice является лучшим в этом отношении. Если вы пытаетесь понять, как это работает, продолжайте читать ...

Теперь проблема с вашим кодом заключается в том, что вы отображаете местоположения от входного изображения до выходного изображения, поэтому вы получаете вывод spotty . Рассмотрим пример, когда входное изображение полностью белое, а выход инициализирован черным, мы получаем следующее:

screenshot

То, что вы должны делать, это наоборот (от вывода к вводу). Для иллюстрации рассмотрим следующие обозначения:

1           c         1                 scaleC*c
+-----------+ 1       +----------------------+ 1
|    |      |         |        |             |
|----o      |   <===  |        |             |
|  (ii,jj)  |         |--------o             |
+-----------+ r       |      (i,j)           |
  inputImage          |                      |
                      |                      |
                      +----------------------+ scaleR*r
                            ouputImage

Note: I am using matrix notation (row/col), so:
  i ranges on [1,scaleR*r] , and j on [1,scaleC*c]
  and ii on [1,r], jj on [1,c]

Идея состоит в том, что для каждого местоположения (i,j) в выходном изображении мы хотим сопоставить его с «ближайшим» местоположением в координатах входного изображения. Поскольку это простое отображение, мы используем формулу, которая отображает данный x в y (с учетом всех других параметров):

 x-minX      y-minY
--------- = ---------
maxX-minX   maxY-minY

в нашем случае x - это координата i / j, а y - это координата ii / jj. Поэтому замена каждого дает нам:

jj = (j-1)*(c-1)/(scaleC*c-1) + 1
ii = (i-1)*(r-1)/(scaleR*r-1) + 1

Соединяя кусочки, мы получаем следующий код:

% read a sample image
inputI = imread('coins.png');
[r,c] = size(inputI);
scale = [2 2];        % you could scale each dimension differently

outputI = zeros(scale(1)*r,scale(2)*c, class(inputI));

for i=1:scale(1)*r
    for j=1:scale(2)*c
        % map from output image location to input image location
        ii = round( (i-1)*(r-1)/(scale(1)*r-1)+1 );
        jj = round( (j-1)*(c-1)/(scale(2)*c-1)+1 );

        % assign value
        outputI(i,j) = inputI(ii,jj);
    end
end

figure(1), imshow(inputI)
figure(2), imshow(outputI)
19 голосов
/ 11 октября 2009

Некоторое время назад я просмотрел код функции imresize в MATLAB Image Processing Toolbox , чтобы создать упрощенную версию для интерполяции изображений только для ближайших соседей. Вот как это будет применяться к вашей проблеме:

%# Initializations:

scale = [2 2];              %# The resolution scale factors: [rows columns]
oldSize = size(inputImage);                   %# Get the size of your image
newSize = max(floor(scale.*oldSize(1:2)),1);  %# Compute the new image size

%# Compute an upsampled set of indices:

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));

%# Index old image to get new image:

outputImage = inputImage(rowIndex,colIndex,:);

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

РЕДАКТИРОВАТЬ: ОБЪЯСНЕНИЕ

В случае, если кому-то будет интересно, я подумал, что объясню, как работает решение выше ...

newSize = max(floor(scale.*oldSize(1:2)),1);

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

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));

Затем вычисляется новый набор индексов как для строк, так и для столбцов. Сначала вычисляется набор индексов для изображения с повышенной дискретизацией: 1:newSize(...). Каждый пиксель изображения считается имеющим заданную ширину, так что пиксель 1 охватывает от 0 до 1, пиксель 2 - от 1 до 2 и т. Д. Таким образом, «координата» пикселя рассматривается как центр, поэтому 0,5 вычитается из индексов. Эти координаты затем делятся на коэффициент масштабирования, чтобы получить набор координат центра пикселей для исходного изображения, к которым затем добавляется 0,5, и они округляются, чтобы получить набор целочисленных индексов для исходного изображения. Вызов min гарантирует, что ни один из этих индексов не будет больше исходного размера изображения oldSize(...).

outputImage = inputImage(rowIndex,colIndex,:);

Наконец, новое изображение с повышенной дискретизацией создается путем простого индексирования исходного изображения.

2 голосов
/ 11 октября 2009

MATLAB уже сделал это для вас. Используйте imresize :

output = imresize(input,size(input)*2,'nearest');

или если вы хотите одинаково масштабировать оба значения x & y,

output = imresize(input,2,'nearest');
0 голосов
/ 11 октября 2009

Вам просто нужна более обобщенная формула для вычисления xloc и yloc.

xloc = (j * (newwidth+1)) / (x+1);
yloc = (i * (newheight+1)) / (y+1);

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

...