Fast average calculation of submatrices in large matrix

조회 수: 12 (최근 30일)
Stijn
Stijn 2013년 5월 24일
Hi,
I have a matrix M=1024x512 elements. What I would like to do is to calculate the average of every submatrix of a size of 4x4 and assign that average to all the elements in that submatrix. Then move on to the next submatrix and do the routine all over again. I have managed to do this by two for loops, but the problem is that I have lots of matrices of this size and this routine is very slow. How can I speed up this calculations? I have the impression that the use of for loops isn't that quick at all :(.
This is the code I used:
for i = 1:4:(1024-4)
for j = 1:4:(512-4)
average = mean(mean(M(i:(i+4-1),j:(j+4-1))));
M(i:(i+4-1),j:(j+4-1)) = average;
end
end
Your help would greatly be apreciated!

채택된 답변

Andrei Bobrov
Andrei Bobrov 2013년 5월 24일
편집: Andrei Bobrov 2013년 5월 24일
PART 1
use function blockproc from Image Processing Toolbox
a1 = blockproc(M,[4,4],@(x)mean2(x.data))
or without blockproc, but with conv2
a1 = conv2(M,ones(4)/16,'valid');
a1 = a1(1:4:end,1:4:end); %CORRECT
or with cellfun
a1 = cellfun(@mean2,mat2cell(M,4*ones(size(M,1)/4,1),4*ones(size(M,2)/4,1)));
average = kron(a1,ones(4));
or
average = cell2mat(arrayfun(@(x)x*ones(4),a1,'un',0));
ADD
average = conv2(M,ones(4)/16,'valid');
  댓글 수: 7
Stijn
Stijn 2013년 6월 11일
can I use blockproc to shift one element in stead of a whole block?

댓글을 달려면 로그인하십시오.

추가 답변 (4개)

Matt J
Matt J 2013년 5월 24일
편집: Matt J 2013년 5월 24일
This will be faster than BLOCKPROC,
kernel=ones(1,4)/4;
M=conv2(kernel, kernel, M,'valid');

Azzi Abdelmalek
Azzi Abdelmalek 2013년 5월 24일
To improve the speed of your code two times:
for i = 1:4:(1024-4)
for j = 1:4:(512-4)
v=M1(i:(i+4-1),j:(j+4-1));
M1(i:(i+4-1),j:(j+4-1)) =mean(v(:));
end
end

Stijn
Stijn 2013년 6월 11일
편집: Stijn 2013년 6월 11일
I want to expand this question a bit. It is in the line of the previous problem, only I would like to do the following:
Suppose I have the following matrix:
m=[1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25]
What i would like to establish here is a some kind of moving average. Instead of jumping ahead with a submatrix of 3x3, I want to move only 1 element forward at the time and calculate the average again and store it a different matrix. To be more clear, suppose you pick an element (say m(2,2)), I want to get an average around that element by averaging the elements m(1:3,1:3), thus go 1 element to each side to get a average vlue of the 3x3 submatrix. (If you use 2 elements to each side you will get an average of a 5x5 submatrix). Only elements on the edges of the matrix are calculated differently.
The matrix would than be obtained like this (I hope this image clarifies it a bit)
  댓글 수: 1
Andrei Bobrov
Andrei Bobrov 2013년 6월 12일
m = [1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25];
[a b] = size(m);
c = true([a b]);
c(2:end-1,2:end-1) = false;
ii = bsxfun(@plus,[0 (b-1)*a],[1;a]);
d = c*6;
d(ii) = 4;
out = conv2(m,ones(3)/9);
out(c) = out(c)*9./d(d>0);

댓글을 달려면 로그인하십시오.


Jan
Jan 2013년 7월 26일
With the C-Mex FEX: BlockMean:
D = rand(1024, 512);
M = BlockMean(M, 4, 4);
M = kron(M, ones(4, 4));

카테고리

Help CenterFile Exchange에서 Creating and Concatenating Matrices에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by