20

我正在尝试编写自己的函数来使用最近邻插值算法来放大输入图像。不好的部分是我能够看到它是如何工作的,但找不到算法本身。我将不胜感激任何帮助。

这是我尝试将输入图像放大 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建议后的输出替代文字

4

4 回答 4

20

这个答案比试图简洁有效的解释性更强。我认为gnovice的解决方案在这方面是最好的。如果您想了解它是如何工作的,请继续阅读...

现在您的代码的问题是您正在将位置从输入图像映射到输出图像,这就是您得到参差不齐的输出的原因。考虑一个输入图像全为白色且输出初始化为黑色的示例,我们得到以下结果:

截屏

你应该做的是相反的(从输出到输入)。为了说明,请考虑以下符号:

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(给定所有其他参数)的公式:

 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)
于 2009-10-11T20:41:36.583 回答
19

不久前,我浏览了MATLAB 图像处理工具箱imresize中的函数代码,为图像的最近邻插值创建了一个简化版本。以下是它将如何应用于您的问题:

%# 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,这就是为什么调用 tomax将任何小于 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,:);

最后,通过简单地对原始图像进行索引来创建新的上采样图像。

于 2009-10-11T17:25:36.120 回答
2

MATLAB 已经为您完成了。使用imresize

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

或者如果你想同时缩放 x & y,

output = imresize(input,2,'nearest');
于 2009-10-11T15:11:13.040 回答
0

您只需要一个更通用的公式来计算 xloc 和 yloc。

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

这假设您的变量有足够的乘法结果范围。

于 2009-10-11T15:01:04.387 回答