Reputation: 47
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
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:
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:
Upvotes: 6