43 views (last 30 days)

Show older comments

Hi everyone. I have an interesting situation. So the idea is to calculate the value of middle points of a 1D, 2D or 3D matrix.

For example, A is a 100*100 matrix. What I want to obtain is an 99*99 matrix which simply represent the averaged value of the 3D matrix A.

I could easily do it by following:

B = (A(2:end,2:end)+A(2:end,1:end-1)+A(1:end-1,2:end)+A(1:end-1,1:end-1))/4;

However, this is rather slow as I need to reference A by 4 times. The situation is worse for 3D or large A. I am just wondering if there is a faster way to do this task by avoiding the multiple referencing or if there is any build-in matlab function that could do it in a faster way?

Thank you very much!

Tommy
on 23 Jun 2020

Edited: Tommy
on 23 Jun 2020

Possibly MATLAB's convolution functions will be faster:

% 1D case:

B = conv(A, ones(2,1), 'valid') / 2;

% 2D case:

B = conv2(A, ones(2), 'valid') / 4;

% 3D case:

B = convn(A, ones(2,2,2), 'valid') / 8;

Generalized for dimension n (I think) by something like this:

B = convn(A, ones([2*ones(1,n),1]), 'valid') / 2^n;

(edit)

Seems to be faster for this case at least:

A = rand(100,100,100);

f1 = @() (A(2:end,2:end,2:end)+A(2:end,2:end,1:end-1)+A(2:end,1:end-1,2:end)+A(2:end,1:end-1,1:end-1)+...

A(1:end-1,2:end,2:end)+A(1:end-1,2:end,1:end-1)+A(1:end-1,1:end-1,2:end)+A(1:end-1,1:end-1,1:end-1))/8;

f2 = @() convn(A, ones(2,2,2), 'valid') / 8;

>> timeit(f1)

ans =

0.0430

>> timeit(f2)

ans =

0.0086

>> all(abs(f1() - f2()) < 0.000000001, 'all')

ans =

logical

1

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

Start Hunting!