Average subset of a matrix in a loop in matlab

I am working with an image that I treat as a matrix.

I want to turn an 800 x 800 matrix (A) into a 400 x 400 matrix (B) where the average of 4 cells of matrix A = 1 cell of matrix B (I know this is not the correct line of code):

B[1,1] =mean2(A[1,1 + 1,2 + 2,1 + 2,2]) 

      

etc. for the whole matrix ...

B [1,2]=mean2(A[1,3 + 1,4 + 2,3 + 2,4 ])

      

I thought:

1) Change matrix A to a 2 x 320,000 matrix so that I get four cells that I need to average next to each other and after that it is easier to handle the row number.

Im4bis=reshape(permute(reshape(Im4,size(Im4,2),2,[]),[2,3,1]),2,[]);

      

2) Create a cell array with 4 cells that I need to average (subset) and calculate the average. What doesn't work there

I{1,160000}=ones,
for k=drange(1:2:319999)
    for n=1:160000
        I{n}=mean2(Im4bis(1:2,k:k+1));
    end
end

      

I created a 400 x 400 empty matrix (actually a 1 x 160000 vector) and I wanted to fill it with the mean, but I got a 1 x 319,999 cell matrix with one cell of 2 blanks.

Looking for light

My input image:

enter image description here

+3


source to share


3 answers


Method 1

Using mat2cell

andcellfun

AC = mat2cell(A, repmat(2,size(A,1)/2,1), repmat(2,size(A,2)/2,1));

out = cellfun(@(x) mean(x(:)), AC);

      

Method 2

using im2col

out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);

      

Method 3

Using a simple for

loop



out(size(A,1)/2,size(A,2)/2) = 0;
k = 1;
for i = 1:2:size(A,1)
    l = 1;
    for j = 1:2:size(A,2)
        out(k,l) = mean(mean(A(i:i+1,j:j+1)));
        l = l+1;
    end
    k = k+1;
end

      

Checking the input image:

A = rgb2gray(imread('inputImage.png'));

%// Here, You could use any of the method from any answers 
%// or you could use the best method from the bench-marking tests done by Divakar
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);  

imshow(uint8(out));  

imwrite(uint8(out),'outputImage.bmp');

      

Output Image:

enter image description here

Final check by reading the already written image

B = imread('outputImage.bmp');

>> whos B

Name        Size              Bytes  Class    Attributes

B         400x400            160000  uint8              

      

+4


source


Let A

denote your matrix and

m = 2; %// block size: rows
n = 2; %// block size: columns

      

Method 1

Use blockproc

:

B = blockproc(A, [m n], @(x) mean(x.data(:)));

      

Example:

>> A = magic(6)
A =
    35     1     6    26    19    24
     3    32     7    21    23    25
    31     9     2    22    27    20
     8    28    33    17    10    15
    30     5    34    12    14    16
     4    36    29    13    18    11
>> B = blockproc(A, [m n], @(x) mean(x.data(:)))
B =
   17.7500   15.0000   22.7500
   19.0000   18.5000   18.0000
   18.7500   22.0000   14.7500

      



Method 2

If you prefer the rearrangement way (which is probably faster), use this excellent answer to arrange the matrix in 2x2 blocks alternating in the third dimension, averaging over the first two dimensions, and change the result:

T = permute(reshape(permute(reshape(A, size(A, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
B = reshape(mean(mean(T,1),2), size(A,1)/m, size(A,2)/n);

      

Method 3

Apply 2D Convolution ( conv2

) and then shrink. Convolution calculates more records than is actually needed (hence the downsampling), but on the other hand it can be done separatively , which helps speed things up to:

B = conv2(ones(m,1)/m, ones(1,n)/n ,A,'same');
B = B(m-1:m:end ,n-1:n:end);

      

+4


source


One approach is based on this solution

using reshape

, sum

and squeeze

-

sublen = 2; %// subset length
part1 = reshape(sum(reshape(A,sublen,[])),size(A,1)/sublen,sublen,[]);
out = squeeze(sum(part1,2))/sublen^2;

      


Benchmarking

Install # 1

Following are the runtime comparisons for the approaches listed so far for data entry 800x 800

-

%// Input
A = rand(800,800);

%// Warm up tic/toc.
for k = 1:50000
    tic(); elapsed = toc();
end

disp('----------------------- With  RESHAPE + SUM + SQUEEZE')
tic
sublen = 2; %// subset length
part1 = reshape(sum(reshape(A,sublen,[])),size(A,1)/sublen,sublen,[]);
out = squeeze(sum(part1,2))/sublen^2;
toc, clear sublen part1 out

disp('----------------------- With  BLOCKPROC')
tic
B = blockproc(A, [2 2], @(x) mean(x.data(:))); %// [m n]
toc, clear B

disp('----------------------- With  PERMUTE + MEAN + RESHAPE')
tic
m = 2;n = 2;
T = permute(reshape(permute(reshape(A, size(A, 1), n, []),...
      [2 1 3]), n, m, []), [2 1 3]);
B = reshape(mean(mean(T,1),2), size(A,1)/m, size(A,2)/m);
toc, clear B T m n

disp('----------------------- With  CONVOLUTION')
tic
m = 2;n = 2;
B = conv2(ones(m,1)/m, ones(1,n)/n ,A,'same');
B = B(m-1:m:end ,n-1:n:end);
toc, clear m n B

disp('----------------------- With  MAT2CELL')
tic
AC = mat2cell(A, repmat(2,size(A,1)/2,1), repmat(2,size(A,2)/2,1));
out = cellfun(@(x) mean(x(:)), AC);
toc

disp('----------------------- With  IM2COL')
tic
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
toc

      

Execution results -

----------------------- With  RESHAPE + SUM + SQUEEZE
Elapsed time is 0.004702 seconds.
----------------------- With  BLOCKPROC
Elapsed time is 6.039851 seconds.
----------------------- With  PERMUTE + MEAN + RESHAPE
Elapsed time is 0.006015 seconds.
----------------------- With  CONVOLUTION
Elapsed time is 0.002174 seconds.
----------------------- With  MAT2CELL
Elapsed time is 2.362291 seconds.
----------------------- With  IM2COL
Elapsed time is 0.239218 seconds.

      

To make runtime fairer, we can use a series of tests 1000

in addition to the fastest three approaches for the same data entry 800 x 800

, giving us

----------------------- With  RESHAPE + SUM + SQUEEZE
Elapsed time is 1.264722 seconds.
----------------------- With  PERMUTE + MEAN + RESHAPE
Elapsed time is 3.986038 seconds.
----------------------- With  CONVOLUTION
Elapsed time is 1.992030 seconds.

      

Install # 2

Following are the runtime comparisons for larger data entry 10000x 10000

for the fastest three approaches -

----------------------- With  RESHAPE + SUM + SQUEEZE
Elapsed time is 0.158483 seconds.
----------------------- With  PERMUTE + MEAN + RESHAPE
Elapsed time is 0.589322 seconds.
----------------------- With  CONVOLUTION
Elapsed time is 0.307836 seconds.

      

+3


source







All Articles