How to change 4x4 matrix to 2x2 matrix

43 views (last 30 days)
Jung
Jung on 7 Nov 2014
Edited: Image Analyst on 9 Nov 2014
I have a 4x4 matrix A = [1 2 3 4; 2 3 4 5; 3 4 5 6; 4 5 6 7]
Now, I'd like to change the matrix size from 4x4 to 2x2 and have the average of 4 cells for new cell.
To visualize,
*1 2* 3 4
*2 3* 4 5
3 4 5 6 2 4
4 5 6 7 --> 4 6
Any input would be appreciated,

Answers (7)

Orion
Orion on 7 Nov 2014
Edited: Orion on 7 Nov 2014
A = [1 2 3 4; 2 3 4 5; 3 4 5 6; 4 5 6 7]
B = cellfun(@mean,cellfun(@mean,mat2cell(A,[2 2],[2 2]),'UniformOutput',false))
A =
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
B =
2 4
4 6
Note : you can simplify by decomposing in several steps if you prefer.
  1 Comment
Jan
Jan on 9 Nov 2014
This is surprisingly slow: it needs about 100 times longer than the other M-versions posted here.

Sign in to comment.


James Tursa
James Tursa on 7 Nov 2014
Edited: James Tursa on 7 Nov 2014
Yet another way (not necessarily any better than other posts), generalized:
kr = 2; kc = 2; % Row and Column sizes of sub-block
[m n] = size(A); mk = m/kr; nk = n/kc; % Size of input and result
B = reshape(sum(reshape(reshape(sum(reshape(A,kr,[])),mk,[]).',kc,[])),nk,mk).'/(kr*kc);

Matt J
Matt J on 7 Nov 2014
Edited: Matt J on 7 Nov 2014
It was for this kind of thing that I wrote SEPBLOCKFUN ( Download ).
Anew = sepblockfun(A,[2,2],@mean);

Jan
Jan on 7 Nov 2014
And if speed matters, FEX: BlockMean.mex will help.

Image Analyst
Image Analyst on 7 Nov 2014
Did you try the straightforward:
out = [A(1,1)+A(1,2)+A(2,1)+A(2,2),...
A(1,3)+A(1,4)+A(2,3)+A(2,4);...
A(3,1)+A(3,2)+A(4,1)+A(4,2),...
A(3,3)+A(3,4)+A(4,3)+A(4,4)]/4

Azzi Abdelmalek
Azzi Abdelmalek on 7 Nov 2014
A = [1 2 3 4; 2 3 4 5; 3 4 5 6; 4 5 6 7]
[n,m]=size(A)
[ii1,jj1]=ndgrid(1:2:n,1:2:m)
out=arrayfun(@(x,y) mean(mean(A(x:x+1,y:y+1))),ii1,jj1)

Jan
Jan on 9 Nov 2014
Edited: Jan on 9 Nov 2014
Some timings for a 1024*768 image, 100 iterations (Matlab R2011b, Win7/64, Core2Duo):
BlockMean: 0.35 sec
CELLFUN: 784.0 sec (wow!)
SUM(RESHAPE): 8.37 sec
SUM(RESHAPE) 2: 5.70 sec
ARRAYFUN: 9.74 sec
SEPBLOCK: 7.50 sec
(BLOCKPROC: Undefined function, I do not have the required toolbox)
function SpeedTest(A)
A = rand(1024, 768);
n = 100;
tic;
for k = 1:n
r = BlockMean(A, 2, 2);
end
fprintf('BlockMean: %.4g sec\n', toc);
tic;
for k = 1:1
[m, n] = size(A);
r = cellfun(@mean, ...
cellfun(@mean, ...
mat2cell(A, repmat(2, 1, m/2), repmat(2, 1, n/2)),'UniformOutput',false));
end
fprintf('CELLFUN: %.4g sec\n', toc * 100);
tic;
for k = 1:n
kr = 2;
kc = 2;
[m, n] = size(A);
mk = m/kr;
nk = n/kc;
B = reshape(sum(reshape( ...
reshape(sum(reshape(A,kr,[])), mk,[]).', kc, [])), nk, mk).' / (kr*kc);
end
fprintf('SUM(RESHAPE): %.4g sec\n', toc);
tic;
for k = 1:n
V = 2;
W = 2;
[M, N] = size(A);
AM = reshape(A, V, M/V, W, N/W, []);
r = sum(sum(AM, 1), 3) .* (1.0 / (V * W));
end
fprintf('SUM(RESHAPE) 2: %.4g sec\n', toc);
tic;
for k = 1:1
[n,m] = size(A);
[ii1, jj1] = ndgrid(1:2:n,1:2:m);
r = arrayfun(@(x,y) mean(mean(A(x:x+1,y:y+1))),ii1,jj1);
end
fprintf('ARRAYFUN: %.4g sec\n', toc);
tic;
for k = 1:n
r = sepblockfun(A, [2,2], @mean);
end
fprintf('SEPBLOCK: %.4g sec\n', toc);
tic;
for k = 1:n
r = blockproc(A,[2,2], @(x) mean(x.data(:)) )
end
fprintf('BLOCKPROC: %.4g sec\n', toc);
  1 Comment
Image Analyst
Image Analyst on 9 Nov 2014
Edited: Image Analyst on 9 Nov 2014
Why did you run the cellfun and arrayfun tests only 1 iteration instead of n iterations like the other tests? By the way, 1 iteration of blockproc took 12 seconds.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!