0

I have a large binary matrix. I want to reduce the size of this matrix by using knn-approximation. What my idea is to cluster the matrix in groups of 4 neighbors and replace the group with a 1, if the number of 1s in the group is greater than or equal to the number of zeros.

To be concrete, let the matrix be

1 0 0 1 0 
0 1 1 0 0 
1 1 0 0 0 
0 1 1 1 0
0 0 1 1 0
1 0 0 1 0

First I want to create neighborhood group as

1 0 |0 1| 0| 
0 1 |1 0| 0|
------------
1 1 |0 0| 0| 
0 1 |1 1| 0|
------------
0 0 |1 1| 0|
------------

and then the final matrix I want to generate is

1 1 0
1 1 0
0 1 0

by replacing the group with the majority score. How can I efficiently do this is MATLAB?

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Shew
  • 1,557
  • 1
  • 21
  • 36
  • Several questions: 1) Will your matrix always divide with a remainder into blocks? 2) Which MATLAB version are you using? 3) Do you have the image processing toolbox? 4) Did you try something already (e.g. `mat2cell`)? – Dev-iL Nov 11 '18 at 08:37
  • 1) nope. as in figure, the remainder is grouped into the remaining size. 2) I am using version 2016b. 3) Yes, I have image processing toolbox. 4) nope. i did not try anything other than splitting using loop. – Shew Nov 11 '18 at 08:40

1 Answers1

1

Initially I tried getting it to work using imresize but couldn't quite get it without "hacks" (it was off by 1 value in all my "proper" attempts).

imresize(M, ceil(size(M)/2), 'bilinear') >= 0.4 % This works but is hacky and not recommended!

However, I can think of a way to solve this using 2D convolution. Note that I pad the array (which requires a toolbox) in order to simplify the indexing stage at the end:

function C = q53247013(M)

if nargin < 1

  M = [
    1 0 0 1 0 
    0 1 1 0 0 
    1 1 0 0 0 
    0 1 1 1 0
    0 0 1 1 0
    1 0 0 1 0];

end

% Constants:
BLK_SZ = 2;
A = ones(BLK_SZ);

% Pad array if needed (note: this WILL require modification if BLK_SZ > 2 ):    
padBottom = rem(size(M,BLK_SZ),1);
padRight = rem(size(M,BLK_SZ),2);
M = padarray(M, [padBottom, padRight], 'replicate', 'post');

% Perform convolution:    
C = conv2(M, A, 'valid') >= ceil(BLK_SZ^2 / 2);

% Remove every other row and column:
C = C(1:2:end, 1:2:end);

Another alternative is the blockproc function:

C = blockproc(M, [2 2], @(x)sum(x.data(:))) >= 2;
Dev-iL
  • 23,742
  • 7
  • 57
  • 99