Moving Standard Deviation issues with NaN values (i.e., Stdfilt). Alternatives and workarounds?
Show older comments
Hi All,
I need to compute a 5x5 moving standard deviation in a matrix I. Also, I need to exclude the central pixel of my moving window from the std computation (see the code below).
The issue is when I have some NaN values, as the stdfilt output returns a sqaure of NaN.
Can you suggest a solution?
Thanks a lot in advance!
(Please see attached my code below)
I = magic(130);
Stdlfilt_neighborhoodSize = [5, 5];
mask_Stdlfilt = true(Stdlfilt_neighborhoodSize);
mask_Stdlfilt(ceil(Stdlfilt_neighborhoodSize(1)/2), ceil(Stdlfilt_neighborhoodSize(2)/2)) = false;
Std_I = stdfilt(I, mask_Stdlfilt);
Accepted Answer
More Answers (2)
NaN values can be substituted with (1) "some value" or (2) next to it value or (3) skip nan values element, e.g.:
A = randi([-3, 3], 10, 5);
B = 0./A;
A(isnan(B))= NaN
%% (2) Substitute NAN with some value
SOME_Value = 2;
A1 = A;
A1(isnan(A1))= SOME_Value
%% (2) with the next value
IDX_nan = find(isnan(A));
IDX_NOT_nan = find(~isnan(A));
A2 = A;
A2(IDX_nan) = A2(IDX_nan+1)
A2(isnan(A2)) = A2(find(isnan(A2))+1) % In case, there are two nans one after another
%% (3) Skip or omit NAN while computing std()
STD_A = std(A, "omitnan")
IPT stdfilt() doesn't behave as you describe in any version I've tested.
% a float array with a 10x10 NaN block
A = magic(130);
A(21:30,21:30) = NaN;
nansin = nnz(isnan(A)) % 10x10
% a 5x5 box filter with a 1px hole
fsz = [5, 5];
fk = true(fsz);
fk(ceil(fsz(1)/2), ceil(fsz(2)/2)) = false;
% the filtered result has no NaNs
B = stdfilt(A, fk);
nansout = nnz(isnan(B)) % no nans
% the 10x10 NaN block turns into a 14x14 block of zeros
% due to the original block size and the filter radius
% i.e. 10 + 2*floor(5/2) = 14
sqrt(nnz(B == 0)) % block width
% see the output region local to the defect
B(16:35,16:35)
Internally, imfilter() is used to do the work, and while the intermediate results from imfilter() will have NaNs, the final output winds up going through
% where do the NaNs turn into zeros?
intermediateresult = [0 100 225 NaN];
output = sqrt(max(intermediateresult,0)) % this is why
which will return 0 for NaNs in the intermediate result.
Either I'm misreading something, or there's something missing from this picture. Is there some other way in which you're using stdfilt() which is producing different results? Are your NaNs sparse, or are they located in large contiguous regions which can span the filter window? Is avoiding NaN throughput the goal, or is it important to instead preserve existing NaNs?
Categories
Find more on Region and Image Properties 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!

