Asked by Andrew McLean
on 17 Feb 2017

As part of an image processing task, I've split a 944x752 (grayscale) image into 11092 8x8 matrices. I've tried using the following for loop to calculate and individually store the means of each matrix:

start=0;

stop=11091;

for cell=start:1:stop

m=mean2(['out_' int2str(cell)]);

eval(['xbar_' int2str(cell) '=m'])

end

This is coming up with results, but the numbers are completely incorrect, for example if I manually enter;

k=mean2(out_3953)

Then k=148.3594, but if I call the result for the corresponding 8x8 block as produced by my for loop, the outcome is 81.375.

I'm new to Matlab and coding in general, so any help or advice would be greatly appreciated.

Answer by Guillaume
on 17 Feb 2017

Edited by Guillaume
on 17 Feb 2017

Accepted Answer

You've really have numbered variables all the way up to out_11091? Wow!

In this forum, we keep telling people not to use eval just to avoid this issue. As soon as you start numbering variables, you're doing it wrong. Very wrong if your numbers go all the way to 11091. Use an array of variable (cell array) or matrices of higher dimension to store all these related variables.

In your case:

%someimage: 2D matrix that can be divided evenly into 8x8 blocks

assert(all(mod(size(someimage), 8) == 0), 'image cannot be divided evenly into 8x8 blocks')

blocks = mat2cell(someimage, repmat(8, 1, size(someimage, 1)/8), repmat(8, 1, size(someimage, 2)/8) %divide image into 8x8 blocks. Store blocks into cell array

xbar = zeros(size(blocks)); %predeclare for faster code

for ib = 1:numel(blocks)

xbar(ib) = mean2(blocks{ib});

end

See how easy the loop is. You don't even need the loop if you use cellfun:

%no need to predeclare xbar since it's created by cellfun

xbar = cellfun(@mean2, blocks);

edit: or as Adam suggest instead of a cell array use a 3D matrix. Easily obtained from the blocks cell array

blocks3D = cat(3, blocks{:});

and the mean is then:

xbar = mean(mean(blocks3D, 1), 2);

The downside of this is you loose the shape of the block matrix. You could always reshape xbar afterward:

xbar = reshape(xbar, size(someimage)/8)

Sign in to comment.

Answer by Image Analyst
on 17 Feb 2017

Image Processing people would use blockproc() for this. You can do this with 2 lines of code if you have the Image Processing Toolbox. Here's a snippet from my demos:

% Block process the image to replace every pixel in the

% 4 pixel by 4 pixel block by the mean of the pixels in the block.

% The image is 256 pixels across which will give 256/4 = 64 blocks.

% Note that the size of the output block (2 by 2) does not need to be the size of the input block!

% Image will be the 128 x 128 since we are using ones(2, 2) and so for each of the 64 blocks across

% there will be a block of 2 by 2 output pixels, giving an output size of 64*2 = 128.

% We will still have 64 blocks across but each block will only be 2 output pixels across,

% even though we moved in steps of 4 pixels across the input image.

meanFilterFunction = @(theBlockStructure) mean2(theBlockStructure.data(:)) * ones(2,2, class(theBlockStructure.data));

blockSize = [4 4];

blockyImage64 = blockproc(grayImage, blockSize, meanFilterFunction);

For your case, replace the blockSize with [8,8] and it does what you want. I'm attaching more comprehensive full demos that do other things too like different resolutions and different operations (median, stdev, etc.).

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Stephen Cobeldick (view profile)

## Direct link to this comment

https://ww2.mathworks.cn/matlabcentral/answers/325569-finding-the-means-of-a-large-number-of-individual-matrices#comment_429605

Sign in to comment.