Подтвердить что ты не робот

Алгоритм интерполяции ближайших соседей в MATLAB

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

Вот что я пробовал для увеличения входного изображения в 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

Вот результат после Mark предложение alt text

4b9b3361

Ответ 1

В то время как я вернулся через код 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, хотя вы упомянули о том, что не хотите использовать встроенные функции в одно из ваших комментариев.

EDIT: ОБЪЯСНЕНИЕ

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

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

Во-первых, чтобы получить новые размеры строк и столбцов, размеры старых строк и столбцов умножаются на коэффициент масштабирования. Этот результат округляется до ближайшего целого числа с floor. Если масштабный коэффициент меньше 1, вы можете получить странный случай, когда один из значений размера равен 0, поэтому вызов max можно заменить что-либо меньшее, чем 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

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

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

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)

Ответ 3

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

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

или если вы хотите масштабировать как x, так и y,

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

Ответ 4

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

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

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