RN95
RN95

Reputation: 47

Subsample an image using a for loop

I have a quick question about subsampling a matrix / image. I am trying to do this while only using for and/or while loops. Basically the question is a reiteration of:

function output = subsample(img,2)

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

However, now I am trying to rewrite the function to do the exact same process but with using for loops and/or while loops and without using two or more ":" (colon) operators and without accessing matrix/vector elements using the colon operator. This is what I have so far:

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

Though what I'm getting is the image resized, it's all black and I'm trying to figure out where I am going wrong or if I am completely wrong. Any help in the right direction will be greatly appreciated.

Upvotes: 0

Views: 2726

Answers (1)

rayryeng
rayryeng

Reputation: 104535

The culprit is the following two statements within your nested for loops:

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

For example, if we set factor = 2, you doing factor*j - 1 to update j will always make j remain the same at each for loop iteration. Specifically, if j = 1 initially, with j <- factor*j - 1, you will get j <- 2*1 - 1 = 1 and you will always get j = 1 no matter what iteration within the loop we are at. Therefore, you only update the top-left corner of the output image and this location will keep overwriting itself until we hit the last pixel of the image, and the top-left corner is finally the last row and last column of the original image. That's probably why you have a black image as you have initialized an output image to be all black pixels, but you're only updating one pixel in the image. As such, you need to change how j (and of course i) is being updated.

I'm also going to change the way you're approaching the problem. Instead, we are going to iterate over the dimensions of the subsampled image, then for each location in the subsampled image, we will pull the right pixel from the original image. Given a row and column location (x,y) in the subsampled image and a subsampling factor factor, the row and column location (j,i) to access from the original image is:

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

This is assuming that x and y both start at 1. If you substitute values of x and y starting from 1,2,... you can see that the above formula picks out the right pixels dependent on factor. For example, if factor = 2, substituting values of x and y of 1,2,... would give:

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

As you can see we are skipping every other pixel, which makes sense as this is a factor of 2. I'll leave it as an exercise, but if you try with any other values, you will see that we are correctly skipping over the right pixels to grab the correct ones from the source to copy over to the output image.

With all of this, here's your modified code:

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

With the above code, I ran this through with cameraman.tif which is part of the sample images that MATLAB comes with if you have the image processing toolbox. It looks like this:

enter image description here

As such, if I want to subsample by a factor of 2, we do:

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

I get:

enter image description here

Upvotes: 6

Related Questions