Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016

How to convert an nXn matrix into n/numXn/num matrix containing the sum of elelments

Asked by Itzik Ben Shabat on 27 Apr 2013

Hi, suppose I have a matrix M which is nXn size. i wish to turn this matrix into a smaller matrix M1 which is n/numXn/num size. each element of M1 will contain the sum of numXnum elements of the original M. for example: M1(1,1)=sum(M(1:num,1:num))

is there a function in matlab that does this in an efficient way or am i forced to use a for loop and handle the case where n/num is not an integer? thanks

0 Comments

Itzik Ben Shabat

Products

No products are associated with this question.

1 Answer

Answer by Cedric Wannaz on 27 Apr 2013
Edited by Cedric Wannaz on 27 Apr 2013
Accepted answer

There is no function, up to my knowledge, that does this automatically (as you can see here, I already posted a similar question [in a different context] that was not answered). It is, however, not too complicated to build a little piece of code for this.

So, If I understand well, you want to compute some block-statistics on M (nxn), using a block size that might not be an integer divider of n.

Let's discuss a simple case:

 >> n = 10 ;
 >> bSize = 3 ;                                   % 3x3 blocks.
 >> M = randi(30, 10, 10)                         % Rand int M for the example.
 M =
    25     5    20    22    14     9    23    26    11     3
    28    30     2     1    12    21     8     8    25     2
     4    29    26     9    23    20    16    25    18    16
    28    15    29     2    24     5    21     8    17    24
    19    25    21     3     6     4    27    28    28    29
     3     5    23    25    15    15    29    11     9     4
     9    13    23    21    14    29    17     6    23    18
    17    28    12    10    20    11     5     8    23    15
    29    24    20    29    22    18     5    19    12     1
    29    29     6     2    23     7     8    15    18    11

The first thing to note is that there are multiple ways to split 10 in blocks of 3 or almost 3.

     3, 3, 3, 1
     3, 3, 2, 2
     3, 2, 3, 2
     4, 3, 3
     etc

and you'll want one or the other way depending on whether you need to have as many 3x3 blocks as possible, or if you want to balance the number of elements in each block.

So you have to choose how you want to define block sizes along both dimensions (you can CIRCSHIFT them to make the distribution of block sizes a little more homogeneous). I'll choose 4,3,3 along both dimensions for the example.

Now one way to achieve what you want is to build a matrix of block IDs, that we use then to summarize M on blocks, i.e

 1   1   1   1   2   2   2   3   3   3
 1   1   1   1   2   2   2   3   3   3
 1   1   1   1   2   2   2   3   3   3
 1   1   1   1   2   2   2   3   3   3
 4   4   4   4   ...
 4   4   4   4   ...
 4   4   4   4   ...
 7   7   7   7   ...
 7   7   7   7   ...
 7   7   7   7   ...

We can build such a matrix as follows:

 >> base = floor((0:n-1) * bSize/n)
 base =
     0     0     0     0     1     1     1     2     2     2
 >> [JJ, II] = meshgrid(base, bSize*base) ;
 >> blockIDs = 1 + II + JJ
 blockIDs =
     1     1     1     1     2     2     2     3     3     3
     1     1     1     1     2     2     2     3     3     3
     1     1     1     1     2     2     2     3     3     3
     1     1     1     1     2     2     2     3     3     3
     4     4     4     4     5     5     5     6     6     6
     4     4     4     4     5     5     5     6     6     6
     4     4     4     4     5     5     5     6     6     6
     7     7     7     7     8     8     8     9     9     9
     7     7     7     7     8     8     8     9     9     9
     7     7     7     7     8     8     8     9     9     9

Now we can obtain any block-stat. using ACCUMARRAY, where we use M as values, and blockIDs as indices. For the sum and the mean per block, for example:

 >> blockSum = accumarray(blockIDs(:), M(:))
 blockSum =
   275
   196
   183
   190
   156
   156
   235
   119
   122
 >> blockMean = accumarray(blockIDs(:), M(:), [], @mean)
 blockMean =
   17.1875
   16.3333
   15.2500
   15.8333
   17.3333
   17.3333
   19.5833
   13.2222
   13.5556

Hope it helps!

0 Comments

Cedric Wannaz

Contact us