Average of the surrounding pixels for each 3x3 matrix, excluding the "outliers" from the count.
2 views (last 30 days)
Show older comments
Dear all,
I ve got several 134x134 double class temperature data matrices.
For each pixel, I need to calculate the average of the surrounding 8 pixels (excluding the central pixel from the calculation).
I do this simply by:
MyMtx % My 134x134 matrix
kernel = ones(3, 3) / 8;
kernel(2, 2) = 0;
bg= nanconv(MyMtx, kernel, 'same');
What I need to do is to compute the average excluding (set to NaN?), the values in each sub matrix falling outside the upper and lower limits, namely those grater than the mean+standard deviation of the 3x3 matrix and those smaller than the mean-standard deviation of the 3x3 matrix, respectively.
For instance, my sub 3x3 matrix is:
MySubMtx=[284.536443397838,285.257928640519,284.887393876757;...
281.380348448367,285.774025332031,284.514456427377;...
274.226936908716,278.793284550825,283.871352790957] % Note: the central pixel is excluded from the average (its weight is 0)
MySubMtxStd=nanstd(MySubMtx(:)) % 3.8919 - Note: the central pixel has to be excluded from the std
MySubMtxAvg=nanmean(MySubMtx(:)) % 282.1835 - Note: the central pixel has to be excluded from the average
UpperLimit=MySubMtxAvg+MySubMtxStd % 286.0754
LowerLimit=MySubMtxAvg-MySubMtxStd % 278.2916
% This would leave me with the average (as resulting from nanconv) computed on this "residual" matrix
MySubMtx=[284.536443397838,285.257928640519,284.887393876757;...
281.380348448367,NaN,284.514456427377;...
NaN,278.793284550825,283.871352790957]
Any help is grately appreciated!
*EDIT:
I managed to write a code that does the job, but it is extremely slow. Would you be able to help me amend the following code to enhance its performance reducing its computational time:
A=magic(134); % Assuming this is my 134x134 matrix
background=NaN(size(A));
Mtx_Siz=134*134;
xmin=1;
xmax=3;
ymin=1;
ymax=3;
for i=1:Mtx_Siz
if ymax<135;
Mask=zeros(size(A));
Mask(ymin:ymax,xmin:xmax)=1;
Mask(ymax-1,xmax-1)=0;
jmask=find(Mask==1);
B=A(jmask);
B_Mean=nanmean(B);
B_std=nanstd(B);
B_Upper=B_Mean+B_std;
B_Lower=B_Mean-B_std;
jout=find(B<B_Lower|B>B_Upper);
B(jout)=NaN;
B_Mean2=nanmean(B);
B_std2=nanstd(B);
background(ymax-1,xmax-1)=B_Mean2;
xmin=xmin+1;
xmax=xmax+1;
if xmax==135;
xmin=1;
xmax=3;
ymin=ymin+1;
ymax=ymax+1;
else
end
else
end
keep A background Mtx_Siz ymin ymax xmin xmax
end
0 Comments
Answers (1)
Antoni Garcia-Herreros
on 14 Apr 2023
Edited: Antoni Garcia-Herreros
on 16 Apr 2023
Hello,
You can try something like this:
Your code takes arround 0.9 seconds to run on my laptop. This one takes 0.06 seconds
clear all
tic
A=magic(134);
[sx,sy]=size(A);
matMEAN=zeros(size(A)); % Matrix containing the mean of the neighboring values
for i=1:sx
for j=1:sy
if i>1 && i<sx && j>1 && j<sy % If index in the central region
subMat=A(i-1:i+1,j-1:j+1); % 3x3 neighbor matrix
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(2,2)=0;
matMEAN(i,j)=mean(subMat(B));
else % If in the boundary
if i==1 && j==1 % Top left corner
subMat=A(i:i+1,j:j+1);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(1,1)=0;
matMEAN(i,j)=mean(subMat(B));
elseif i==1 && j>1 && j<sy %Top boundary
subMat=A(i:i+1,j-1:j+1);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(1,2)=0;
matMEAN(i,j)=mean(subMat(B));
elseif j==1 && i>1 && i<sx %Left boundary
subMat=A(i-1:i+1,j:j+1);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(2,1)=0;
matMEAN(i,j)=mean(subMat(B));
elseif j==sy && i>1 && i<sx %Right boundary
subMat=A(i-1:i+1,j-1:j);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(2,2)=0;
matMEAN(i,j)=mean(subMat(B));
elseif i==sx && j>1 && j<sy %Bottom boundary
subMat=A(i-1:i,j-1:j+1);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(2,2)=0;
matMEAN(i,j)=mean(subMat(B));
elseif i==sx && j==1 % Bottom right corner
subMat=A(i-1:i,j:j+1);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(2,1)=0;
matMEAN(i,j)=mean(subMat(B));
elseif i==sx && j==sy % Bottom left corner
subMat=A(i-1:i,j-1:j);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(2,2)=0;
matMEAN(i,j)=mean(subMat(B));
elseif i==1 && j==sy % Top left corner
subMat=A(i:i+1,j-1:j);
uplim=nanmean(subMat(:))+nanstd(subMat(:));
lowlim=nanmean(subMat(:))-nanstd(subMat(:));
B=subMat>lowlim & subMat<uplim;
B(1,2)=0;
matMEAN(i,j)=mean(subMat(B));
end
end
end
end
toc
Hope this helps
2 Comments
Antoni Garcia-Herreros
on 16 Apr 2023
Yes, you are right! There was a mistake in the first " if " statement, I just eddited the code.
See Also
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!