Skip to content

Commit

Permalink
image voi
Browse files Browse the repository at this point in the history
  • Loading branch information
scott committed Mar 29, 2017
1 parent 049d133 commit 40140be
Show file tree
Hide file tree
Showing 6 changed files with 419 additions and 2 deletions.
279 changes: 279 additions & 0 deletions OutSideFunctions/sffilt.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
function B = sffilt(func,A,siz,padopt,CHUNKFACTOR)

%SFFILT Scalar function-based filtering.
% SFFILT(FUNC,A,...) replaces each element in the 1D, 2D or 3D array A by
% the scalar issued from the function FUNC applied on the elements in the
% neighborhood around the corresponding pixel. FUNC must be a scalar
% function.
%
% FUNC can be a string that represents a function ('max', 'min', 'mean',
% 'median', 'std', 'var', 'sum', 'prod', 'nanmean',...), a function
% handle (@max, @median, @sum,...) or an inline function object.
%
% Some typical filters:
% 'mean' or @mean: averaging filter
% 'median' or @median: median filtering
% 'max' or @max: image dilation
% 'min' or @min: image erosion
% Create your own root-mean-square filter:
% rms = @(x) sqrt(mean(x.^2));
% B = sffilt(rms,A);
%
% B = SFFILT(FUNC,A,[M N P]) performs scalar-function filtering of the
% 3-D array A. Each output pixel contains the scalar FUNC value in the
% M-by-N-by-P neighborhood around the corresponding pixel in the input
% array.
%
% B = SFFILT(FUNC,A,[M N]) performs scalar-function filtering of the
% matrix A. Each output pixel contains the scalar FUNC value in the
% M-by-N neighborhood around the corresponding pixel.
%
% B = SFFILT(FUNC,A,M) performs scalar-function filtering of the vector
% A. Each output pixel contains the scalar FUNC value in the M
% neighborhood around the corresponding pixel.
%
% B = SFFILT(FUNC,A) performs scalar-function filtering using a 3 or 3x3
% or 3x3x3 neighborhood according to the size of A.
%
% B = SFFILT(FUNC,A,DOMAIN) replaces each element in A by the scalar
% calculated from the set of neighbors specified by the nonzero elements
% in DOMAIN. DOMAIN is equivalent to the structuring element used for
% binary image operations. It is a matrix containing only 1's and 0's;
% the 1's define the neighborhood for the filtering operation. For
% example, B = SFFILT('max',A,[0 1 0; 1 0 1; 0 1 0]) replaces each
% element in A by the maximum of its north, east, south, and west
% neighbors. The size of the domain must be odd in each direction.
%
% B = SFFILT(FUNC,A,...,PADOPT) pads array A using PADOPT option:
%
% String values for PADOPT (default = 'replicate'):
% 'circular' Pads with circular repetition of elements.
% 'replicate' Repeats border elements of A. (DEFAULT)
% 'symmetric' Pads array with mirror reflections of itself.
%
% If PADOPT is a scalar, A is padded with this scalar.
%
% Notes
% -----
% IMPORTANT: The scalar function FUNC must work across the first
% non-singleton dimension by default (e.g. max, min, trapz, mean,
% median, sum, std, var, prod, nanmean, nanmedian...).
%
% M, N and P must be odd integers. If not, they are incremented by 1.
%
% If you do not have the Image Processing Toolbox, A can only be padded
% with a scalar (default = zero-padding).
%
% If you work with very large 3D arrays, an "Out of memory" error may
% appear. The chunk factor (CHUNKFACTOR, default value = 1) must be
% increased to further reduce the size of the chunks. Use the following
% syntax: SFFILT(FUNC,A,[...],PADOPT,CHUNKFACTOR).
%
% Examples
% --------
% %>> Some 2-D examples using a 3x3 neighborhood:
% A = rand(10,10);
% Amean = sffilt('mean',A); % or Amean = sffilt(@mean,A);
% Amed = sffilt('median',A);
% Amax = sffilt('max',A);
% rms = @(x) sqrt(mean(x.^2));
% Arms = sffilt(rms,A);
%
% %>> 1-D scalar-function filtering using MEAN <<
% % This examples uses a mean filter with a 11 neighborhood.
% t = linspace(0,2*pi,200);
% y = cos(t)+(rand(1,200)-0.5)/5;
% ys = sffilt('mean',y,11);
% plot(t,y,'g',t,ys,'k')
%
% %>> 2-D scalar-function filtering using MAX <<
% % This examples uses a maximum filter with a [5 5] neighborhood.
% % This is equivalent to imdilate(image,strel('square',5)).
% A = imread('snowflakes.png');
% B = sffilt('max',A,[5 5]);
% figure, subplot(211), imshow(A), subplot(212), imshow(B)
%
% %>> 3-D scalar-function filtering using MEDIAN <<
% % This examples uses a median filter with a [3 3 3] neighborhood.
% % This is equivalent to medfilt3(array).
% rand('state',0)
% [x,y,z,V] = flow(50);
% noisyV = V + 0.1*double(rand(size(V))>0.95);
% clear V
% figure
% subplot(121)
% hpatch = patch(isosurface(x,y,z,noisyV,0));
% isonormals(x,y,z,noisyV,hpatch)
% set(hpatch,'FaceColor','red','EdgeColor','none')
% daspect([1,4,4]), view([-65,20]), axis tight off
% camlight left; lighting phong
% subplot(122)
% %--------
% denoisedV = sffilt('median',noisyV);
% %--------
% hpatch = patch(isosurface(x,y,z,denoisedV,0));
% isonormals(x,y,z,denoisedV,hpatch)
% set(hpatch,'FaceColor','red','EdgeColor','none')
% daspect([1,4,4]), view([-65,20]), axis tight off
% camlight left; lighting phong
%
% See also MEDFILT3, ORDFILT2, FSPECIAL3
%
% -- Damien Garcia -- 2008/01, revised 2008/02

error(nargchk(2,5,nargin))

%% Note:
% If you work with large 3D arrays, an "Out of memory" error may appear.
% The chunk factor thus must be increased to reduce the size of the chunks.
if nargin~=5
CHUNKFACTOR = 1;
end
if CHUNKFACTOR<1, CHUNKFACTOR = 1; end

%% Check if FUNC is a scalar function
if ischar(func), func = strtrim(func); end
try
B = feval(func,rand(1,3));
if ~isscalar(B), error(' '), end
catch
error('FUNC argument is not a scalar function.')
end

%% Check input arguments
if isscalar(A), B = feval(func,A); return, end

if ndims(A)>3
error('A must be a 1-D, 2-D or 3-D array.')
end

if all(isnan(A(:))), B = A; return, end

sizA = size(A);
if nargin==2
% default kernel size is 3 or 3x3 or 3x3x3
if isvector(A)
siz = 3;
else
siz = 3*ones(1,numel(sizA));
end
padopt = 'replicate';
elseif nargin==3
% default padding option is "replicate"
padopt = 'replicate';
end

%% Check if SIZ represents a DOMAIN (i.e. contains only 0 and 1)
test = isequal((siz==0)+(siz==1),true(size(siz)));
if test
domain = logical(siz);
siz = size(domain);
if any(rem(siz,2)==0)
error('The size of the domain must be odd.')
end
else
I = rem(siz,2)==0;
siz(I) = siz(I)+1;
domain = true(siz);
end

%% Make SIZ a 3-element array
if numel(siz)==2
siz = [siz 1];
elseif isscalar(siz)
if sizA(1)==1
siz = [1 siz 1];
else
siz = [siz 1 1];
end
end

%% Chunks: the numerical process is split up in order to avoid large arrays
N = numel(A);
n = prod(siz);
siz = (siz-1)/2;
nchunk = (1:ceil(N/n/CHUNKFACTOR):N);
if nchunk(end)~=N, nchunk = [nchunk N]; end

%% Check if FUNC works with other classes than single and double
class0 = class(A);
if ~isa(A,'float')
try
feval(func,uint8(0));
catch
A = double(A);
end
end

%% Padding along specified direction
% If PADARRAY exists (Image Processing Toolbox), this function is used.
% Otherwise the array is padded with scalars.
B = A;
sizB = sizA;
try
A = padarray(A,siz,padopt);
catch
if ~isscalar(padopt)
padopt = 0;
warning('MATLAB:sffilt:InexistentPadarrayFunction',...
['PADARRAY function does not exist: '...
'only scalar padding option is available.\n'...
'If not specified, the scalar 0 is used as default.']);
end
A = ones(sizB+siz(1:ndims(B))*2)*padopt;
A(siz(1)+1:end-siz(1),siz(2)+1:end-siz(2),siz(3)+1:end-siz(3)) = B;
end
sizA = size(A);

if numel(sizB)==2
sizA = [sizA 1];
sizB = [sizB 1];
end

%% Creating the index arrays (INT32)
inc = zeros([3 2*siz+1],'int32');
siz = int32(siz);
[inc(1,:,:,:) inc(2,:,:,:) inc(3,:,:,:)] = ndgrid(...
[0:-1:-siz(1) 1:siz(1)],...
[0:-1:-siz(2) 1:siz(2)],...
[0:-1:-siz(3) 1:siz(3)]);
inc = reshape(inc,[1 3 prod(2*single(siz)+1)]);

I = zeros([sizB 3],'int32');
sizB = int32(sizB);
[I(:,:,:,1) I(:,:,:,2) I(:,:,:,3)] = ndgrid(...
(1:sizB(1))+siz(1),...
(1:sizB(2))+siz(2),...
(1:sizB(3))+siz(3));
I = reshape(I,[prod(single(sizB)) 3]);

%% Filtering
for i = 1:length(nchunk)-1

Im = repmat(I(nchunk(i):nchunk(i+1),:),[1 1 n]);
Im = Im + repmat(inc,[nchunk(i+1)-nchunk(i)+1,1,1]);
I0 = Im(:,1,:) +...
(Im(:,2,:)-1)*sizA(1) +...
(Im(:,3,:)-1)*sizA(1)*sizA(2);
I0 = squeeze(I0);
if i==1
[tmp,tmpI] = sort(I0(1,:));
domain = domain(tmpI);
clear tmp*
end
I0 = I0(:,domain(:));
if ~isvector(I0)
B(nchunk(i):nchunk(i+1)) = feval(func,A(I0'));
else
% Matlab functions work across the first non-singleton dimension.
% One must do a pixel-by-pixel evaluation (loop!) if I0 is a vector.
for j = nchunk(i):nchunk(i+1)
B(j) = feval(func,A(I0(j-nchunk(i)+1)));
end
end

end

%% Change the class
B = cast(B,class0);

Binary file added svca4_imageTACGui.fig
Binary file not shown.
Loading

0 comments on commit 40140be

Please sign in to comment.