20

我正在嘗試編寫自己的函數來使用最近鄰居插值算法來放大輸入圖像。不好的部分是我能夠看到它是如何工作的,但無法找到算法本身。我會很感激任何幫助。MATLAB中的最近鄰居插值算法

這裏就是我試圖通過的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

+0

對不起,不知道我在想什麼 - 你需要遍歷輸出,不輸入,因爲輸出較大。在這種情況下,我的公式需要顛倒。 – 2009-10-12 00:47:17

回答

19

前陣子我在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

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接下來,爲行和列計算一組新的索引。首先,計算上採樣圖像的一組索引:1:newSize(...)。每個圖像像素被認爲具有給定的寬度,使得像素1跨越0到1,像素2跨越1到2等。像素的「座標」因此被視爲中心,這就是爲什麼0.5從指數中減去。然後將這些座標除以縮放因子以給出原始圖像的一組像素中心座標,然後將0.5添加到它們並四捨五入以獲得原始圖像的一組整數索引。致電min確保這些指數均不大於原始圖像尺寸oldSize(...)

outputImage = inputImage(rowIndex,colIndex,:); 

最後,通過索引到原始圖像中創建新的上採樣圖像。

+0

很好,謝謝! – Hellnar 2009-10-11 17:50:33

+0

@Hellnar:很高興幫助!我還更新了代碼,以便它適用於非整數比例因子以及灰度或RGB圖像。 – gnovice 2009-10-11 22:06:47

0

你只需要計算一個更通用的公式xloc和yloc。

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

這假設你的變量有足夠的範圍來乘法結果。

2

MATLAB已經爲你做了。使用imresize

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

,或者如果你想同樣同時調整X & Y,

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

我已經意識到內置函數,但我需要通過自己的代碼來實現。 謝謝 – Hellnar 2009-10-11 15:22:45

+1

對不起,不知道!很高興看到你找到你的答案。 – Jacob 2009-10-11 18:42:10

20

這個答案比試圖簡潔和高效更具有解釋性。我認爲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),我們希望把它映射到輸入圖像座標「最近」的位置。由於這是一個簡單的映射,我們使用映射給定xy(給所有其他PARAMS)式中:

x-minX  y-minY 
--------- = --------- 
maxX-minX maxY-minY 
在我們的例子

xi/j協調和yii/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) 
+0

gnovice的解決方案快了大約10倍。但是,感謝您的解釋! – Wok 2011-05-31 13:47:11

+0

當使用Izoom最近的鄰居對圖像進行縮放,然後Izoom被相同的因子收縮時,我們會恢復原始圖像I.現在,直觀地瞭解,由於我們只進行像素複製而不進行任何平均,這很自然,但我似乎找不到更嚴格的證據。我希望這裏有人能給我一些關於這方面的指導。 – idexi 2015-08-29 23:26:06