Moving Standard Deviation issues with NaN values (i.e., Stdfilt). Alternatives and workarounds?
8 次查看(过去 30 天)
显示 更早的评论
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);
0 个评论
采纳的回答
William Rose
2023-12-19
编辑:William Rose
2023-12-19
[Edit: I attached the script twice. I am removing the earlier version.]
See attached script. Key steps, which occur inside a loop, are shown below. In the code below, img2 is the image, with NaNs. img2std is the array of standard deviations of img2. sn is the number of points in the st.dev mask. shw is the half-width of the st.dev. mask, rounded down. When the mask is 5x5, sn=25 and shw=2.
A=img2(i-shw:i+shw,j-shw:j+shw); % extract the chunk of the image
A=reshape(A,sn,1); % make A a vector
A((sn+1)/2)=[]; % delete the central element
img2std(i,j)=std(A(~isnan(A))); % stdev(A without NaNs)
The code above computes the st.dev. of A, with the central element and any NaNs removed.
This script generates and displays three images, shown below: the original "magic(130)" image, the original plus NaNs at a random 5% of the pixels, and the st.dev. across the image.
5 个评论
William Rose
2023-12-20
You are welcome.
I don't know why Method 2 gives st.devs. that are sometimes a tiny bit different than the values reported by the Methods 1 and 3. The max StDev is 7714, the mean StDev is 699, so differences of ~10^-12 are irrelevant.
Method 2 is interesting. The idea is: 1. Make an augmented image by adding a 1-pixel-wide strip of NaNs all around the original image. 2. Make a 3D array which is a 24-layer stack of copies of the augmented image. 3. Do a circular shift of each of the 24 layers, so that a drill-down through the stack will hit the 24 points of the 5x5 mask (minus the central point). 4. Compute the StDev of each 24-layer stack of pixels.
更多回答(2 个)
Sulaymon Eshkabilov
2023-12-19
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")
0 个评论
DGM
2023-12-19
编辑:DGM
2023-12-19
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?
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Orange 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!