2

Say I have a matrix A, which is of dimension 4x4.

Now I want to downsample this matrix by a factor 2 to get a new matrix B of dimension 2x2.

I want to downsample in the following way :

Let A be

 1     5     9    13
 2     6    10    14
 3     7    11    15
 4     8    12    16

I want B to be

3.5000   11.5000
5.5000   13.5000 

To get B(1,1) = I take mean (1, 5, 2 and 6)

To get B(1,2) = I take mean (9, 13, 10 and 14)

To get B(2,1) = I take mean (3, 7, 4 and 8) and so on.

So for every element in B, I take the corresponding 2x2 block from A and take the mean of it.

In my case, the matrix A is of large dimension. Also, the downsampling factor could be arbitrary.

For example, A =

 1     7    13    19    25    31
 2     8    14    20    26    32
 3     9    15    21    27    33
 4    10    16    22    28    34
 5    11    17    23    29    35
 6    12    18    24    30    36

For downsampling of size 3/2.

Matrix B will be of size 4x4.

For every B unit I would have to take non-overlapping 1.5x1.5 blocks of A.

For example,

B(1,1) = mean(1, 0.5x7, 0.5x2, 0.5x8)

B(2,1) = mean(0.5x2, 0.5x8, 3, 9)

B(3,1) = mean(4, 0.5x10, 0.5x5, 0.5x11)

B(4,1) = mean(0.5x5, 0.5x11, 6, 12)

and so on.

Is there a faster way to do this without for loops?

2 Answers2

3

How about this:

A = [1     5     9    13;
 2     6    10    14;
 3     7    11    15;
 4     8    12    16];

B = ones(2)/4;

out = conv2(A,B,'valid');

%{
out = [3.5000    7.5000   11.5000;
4.5000    8.5000   12.5000;
5.5000    9.5000   13.5000];
%}

This gives you a little more than what you asked for, but you can throw away the information you don't need. For this case, you'd only be interested in out(1,1) , out(1,3) out (3,1) and out(3,3)

willpower2727
  • 769
  • 2
  • 8
  • 23
  • You can complete the answer by doing `out = out(1:2:end,1:2:end);`. This is pretty much the same approach I took in the duplicate post. – rayryeng Apr 10 '15 at 19:36
  • Oh shoot @rayryeng I didn't even think to look for a duplicate haha that's good you marked it. – Benoit_11 Apr 10 '15 at 20:27
  • @Benoit_11 - Haha no worries. I only knew about it because I answered a similar question a couple of days ago. If I didn't do that, I wouldn't have marked as a duplicate because I wouldn't know where to look! I still upvoted both answer regardless. – rayryeng Apr 10 '15 at 20:29
  • @Benoit_11 - BTW, lots of activity on my question. I've revised my post to take advantage of `scatter`. Thanks for the tip! – rayryeng Apr 10 '15 at 20:29
  • @rayryeng Awesome then glad to help! I'll follow the updates on your question :) – Benoit_11 Apr 10 '15 at 21:32
  • @rayryeng : I edited the question now. I want arbitary downsampling factor. – Adithyan Ilangovan Apr 11 '15 at 11:50
  • @AdithyanIlangovan - That's a new question all together. Editing won't guarantee that it will be reopen. Please make a new question. – rayryeng Apr 12 '15 at 02:19
  • @rayryeng Sorry, I am new to this. I just added an extra example to make it more clear. I wanted arbitary non-integer downsampling in the first place. Should I open a new question? Thanks for the help. – Adithyan Ilangovan Apr 13 '15 at 09:40
1

If you have the Image Processing Toolbox you can make use of blockproc:

fun = @(block_struct) mean2(block_struct.data) * ones(size(block_struct.data));
B = blockproc(A,[2 2],fun);

B = reshape(unique(B),2,[])

Output:

A =

     1     5     9    13
     2     6    10    14
     3     7    11    15
     4     8    12    16


B =

          3.5         11.5
          5.5         13.5

Where you can replace the block size by any factor you want. Note that for non-integer factors MATLAB will truncate them.

Benoit_11
  • 13,905
  • 2
  • 24
  • 35