1## Copyright (C) 2008 Søren Hauberg <soren@hauberg.org> 2## 3## This program is free software; you can redistribute it and/or modify it under 4## the terms of the GNU General Public License as published by the Free Software 5## Foundation; either version 3 of the License, or (at your option) any later 6## version. 7## 8## This program is distributed in the hope that it will be useful, but WITHOUT 9## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 11## details. 12## 13## You should have received a copy of the GNU General Public License along with 14## this program; if not, see <http://www.gnu.org/licenses/>. 15 16## -*- texinfo -*- 17## @deftypefn {Function File} {} ordfiltn (@var{A}, @var{nth}, @var{domain}) 18## @deftypefnx {Function File} {} ordfiltn (@var{A}, @var{nth}, @var{domain}, @var{S}) 19## @deftypefnx {Function File} {} ordfiltn (@dots{}, @var{padding}) 20## N dimensional ordered filtering. 21## 22## Ordered filter replaces an element of @var{A} with the @var{nth} element 23## element of the sorted set of neighbours defined by the logical 24## (boolean) matrix @var{domain}. 25## Neighbour elements are selected to the sort if the corresponding 26## element in the @var{domain} matrix is true. 27## 28## The optional variable @var{S} is a matrix of size(@var{domain}). 29## Values of @var{S} corresponding to nonzero values of domain are 30## added to values obtained from @var{A} when doing the sorting. 31## 32## Optional variable @var{padding} determines how the matrix @var{A} 33## is padded from the edges. See @code{padarray} for details. 34## 35## @seealso{medfilt2, padarray, ordfilt2} 36## @end deftypefn 37 38## This function is based on 'ordfilt2' by Teemu Ikonen <tpikonen@pcu.helsinki.fi> 39## which is released under GPLv2 or later. 40 41function retval = ordfiltn (A, nth, domain, varargin) 42 43 ## Check input 44 if (nargin < 3) 45 print_usage (); 46 elseif (! isnumeric (A) && ! islogical (A)) 47 error ("ordfiltn: A must be a numeric or logical array"); 48 elseif (! isscalar (nth) || nth <= 0 || fix (nth) != nth) 49 error ("ordfiltn: second input argument must be a positive integer"); 50 elseif (! isnumeric (domain) && ! islogical (domain)) 51 error ("ordfiltn: DOMAIN must be a numeric or logical array or scalar"); 52 elseif (isscalar (domain) && (domain <= 0 || fix (domain) != domain)) 53 error ("ordfiltn: third input argument must be a positive integer, when it is a scalar"); 54 endif 55 56 if (isscalar (domain)) 57 domain = true (repmat (domain, 1, ndims (A))); 58 endif 59 60 if (ndims (A) != ndims (domain)) 61 error ("ordfiltn: first and second argument must have same dimensionality"); 62 elseif (any (size (A) < size (domain))) 63 error ("ordfiltn: domain array cannot be larger than the data array"); 64 endif 65 66 ## Parse varargin 67 S = zeros (size (domain)); 68 padding = 0; 69 for idx = 1:length(varargin) 70 opt = varargin{idx}; 71 if (ischar (opt) || isscalar (opt)) 72 padding = opt; 73 elseif (isnumeric (opt) && size_equal (opt, domain)) 74 S = opt; 75 else 76 error ("ordfiltn: unrecognized option from input argument #%i and class %s", 3 + idx, class (opt)); 77 endif 78 endfor 79 80 A = pad_for_sliding_filter (A, size (domain), padding); 81 82 ## Perform the filtering 83 retval = __spatial_filtering__ (A, logical (domain), "ordered", S, nth); 84 85endfunction 86 87%!shared b, f, s 88%! b = [ 0 1 2 3 89%! 1 8 12 12 90%! 4 20 24 21 91%! 7 22 25 18]; 92%! 93%! f = [ 8 12 12 12 94%! 20 24 24 24 95%! 22 25 25 25 96%! 22 25 25 25]; 97%!assert (ordfiltn (b, 9, true (3)), f); 98%! 99%! f = [ 1 8 12 12 100%! 8 20 21 21 101%! 20 24 24 24 102%! 20 24 24 24]; 103%!assert (ordfiltn (b, 8, true (3)), f); 104%! 105%! f = [ 1 2 8 12 106%! 4 12 20 21 107%! 8 22 22 21 108%! 20 24 24 24]; 109%!assert (ordfiltn (b, 7, true (3), "symmetric"), f); 110%! 111%! f = [ 1 8 12 12 112%! 4 20 24 21 113%! 7 22 25 21 114%! 7 22 25 21]; 115%!assert (ordfiltn (b, 3, true (3, 1)), f); 116%! 117%! f = [ 1 8 12 12 118%! 4 20 24 18 119%! 4 20 24 18 120%! 4 20 24 18]; 121%!assert (ordfiltn (b, 3, true (4, 1)), f); 122%! 123%! f = [ 4 20 24 21 124%! 7 22 25 21 125%! 7 22 25 21 126%! 7 22 25 21]; 127%!assert (ordfiltn (b, 4, true (4, 1)), f); 128%! 129%! s = [0 0 1 130%! 0 0 1 131%! 0 0 1]; 132%! f = [ 2 8 12 12 133%! 9 20 22 21 134%! 21 25 24 24 135%! 21 25 24 24]; 136%!assert (ordfiltn (b, 8, true (3), s), f); 137%! 138%! b(:,:,2) = b(:,:,1) - 1; 139%! b(:,:,3) = b(:,:,2) - 1; 140%! f(:,:,1) = [ 1 8 11 11 141%! 8 20 21 21 142%! 20 24 24 24 143%! 20 24 24 24]; 144%! f(:,:,2) = [ 6 10 11 11 145%! 18 22 22 22 146%! 20 24 24 24 147%! 20 24 24 24]; 148%! f(:,:,3) = [ 0 7 10 10 149%! 7 19 20 20 150%! 19 23 23 23 151%! 19 23 23 23]; 152%!assert (ordfiltn (b, 25, true (3, 3, 3)), f); 153