使用 for 循环对图像进行子采样

Subsample an image using a for loop

我有一个关于对矩阵/图像进行子采样的快速问题。我正在尝试仅使用 for and/or while 循环来执行此操作。基本上问题是重申:

function output = subsample(img,2)

output = img(1:factor:end, 1:factor:end);

但是,现在我正在尝试重写函数以执行完全相同的过程,但使用 for 循环 and/or while 循环并且不使用两个或更多“:"(冒号)运算符,并且不使用冒号运算符访问 matrix/vector 元素。这是我目前所拥有的:

function output = subsamplex(img,factor)

[r, c] = size(img);

output = zeros(r/factor,c/factor);

j = 1;

i = 1;

for x = 1:r;

    for y = 1:c;
        j = factor*j-1;
        i = factor*i-1;
        output(j,i) = img(x,y);
    end
end

end

虽然我得到的是调整了大小的图像,但它全黑了,我想弄清楚我哪里出错了,或者我是否完全错了。任何正确方向的帮助将不胜感激。

罪魁祸首是嵌套 for 循环中的以下两个语句:

j = factor*j-1;
i = factor*i-1;

例如,如果我们设置 factor = 2,你做 factor*j - 1 更新 j 将始终使 j 在每个 for 循环中保持不变迭代。具体来说,如果最初 j = 1,使用 j <- factor*j - 1,您将得到 j <- 2*1 - 1 = 1,并且无论我们处于循环中的哪个迭代,您将始终得到 j = 1。因此,您只更新输出图像的 top-left 角,这个位置将不断覆盖自身,直到我们到达图像的最后一个像素,并且 top-left 角最终是最后一行和最后一列原始图像。这可能就是为什么您将输出图像初始化为全黑色像素时得到黑色图像的原因,但您只更新了图像中的一个像素。因此,您需要更改 j(当然还有 i)的更新方式。

我还将改变您处理问题的方式。相反,我们将迭代 subsampled 图像的维度,然后对于二次采样图像中的每个位置,我们将从原始图像中提取正确的像素。给定子采样图像中的行和列位置 (x,y) 和子采样因子 factor,从原始图像访问的行和列位置 (j,i) 是:

j = factor*(x-1) + 1;
i = factor*(y-1) + 1;

这是假设 xy 都从 1 开始。如果您从 1,2,... 开始替换 xy 的值,您可以看到上面的公式根据 factor 挑选出正确的像素。例如,如果 factor = 2,将 x 的值和 1,2,...y 的值替换为:

j = 1, 3, 5, ...
i = i, 3, 5, ...

如您所见,我们正在跳过所有其他像素,这是有道理的,因为这是 2 的因数。我会把它留作练习,但如果您尝试使用任何其他值,您会发现我们正确地跳过正确的像素以从源中获取正确的像素以复制到输出图像。

有了所有这些,这是您修改后的代码:

function output = subsamplex(img,factor)

[r, c] = size(img);

output = zeros(r/factor,c/factor,class(img)); %// Cast to be sure
[rnew, cnew] = size(output); %// Change - get size of output

for x = 1:rnew %// Change for loop limits
    for y = 1:cnew
        j = factor*(x-1) + 1; %// Change
        i = factor*(y-1) + 1;
        output(x,y) = img(j,i);
    end
end

end

使用上面的代码,我 运行 通过 cameraman.tif 这是 MATLAB 附带的示例图像的一部分,如果您有图像处理工具箱的话。它看起来像这样:

因此,如果我想以 2 为因子进行子采样,我们会这样做:

img = imread('cameraman.tif');
out = subsamplex(img, 2);
imshow(out); %// Show the image

我得到: