changeset 11377:fff993191048 octave-forge

medfilt2 fixes, tests and documentation. * if specifying filter size, use MxN instead of NxM filter * deprecate non-logical matrix when specifying neighborhood instead of its size * more tests * improved documentation with examples
author carandraug
date Sun, 13 Jan 2013 23:38:26 +0000
parents 1c186f4255de
children dcde9f1576d4
files main/image/NEWS main/image/inst/medfilt2.m
diffstat 2 files changed, 106 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/main/image/NEWS	Sat Jan 12 15:50:13 2013 +0000
+++ b/main/image/NEWS	Sun Jan 13 23:38:26 2013 +0000
@@ -15,6 +15,10 @@
 
       imrotate_Fourier
 
+ ** The use of non logical matrices to specify the neighborhood for the medfilt2
+    function has been deprecated.  If using a vector to specify the size of the
+    neighborhood, the elements are no longer swapped.
+
  ** The plot produced by `imhist' is correctly scaled on the X axis so that the
     colorbar corresponds to the actual intensity of the stems; the given
     colormarp is used on the colorbar for indexed images; and the stems no
--- a/main/image/inst/medfilt2.m	Sat Jan 12 15:50:13 2013 +0000
+++ b/main/image/inst/medfilt2.m	Sun Jan 13 23:38:26 2013 +0000
@@ -14,50 +14,117 @@
 ## this program; if not, see <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} medfilt2(@var{A}, [@var{domain}, @var{padding}])
+## @deftypefn  {Function File} {} medfilt2 (@var{A})
+## @deftypefnx {Function File} {} medfilt2 (@var{A}, @var{nhood})
+## @deftypefnx {Function File} {} medfilt2 (@var{A}, [@var{M} @var{N}])
+## @deftypefnx {Function File} {} medfilt2 (@dots{}, @var{pad})
 ## Two dimensional median filtering.
 ##
-## Replaces elements of @var{A} with the median of their neighbours defined 
-## by true elements of logical matrix @var{domain}. The default @var{domain} 
-## is a 3 by 3 matrix with all elements equal to 1. If @var{domain} is 1 by 2
-## row vector, the domain matrix will be 
-## logical(ones(@var{domain}(2), @var{domain}(1))).
+## Replaces elements of @var{A} with the median of their neighbours as defined
+## by the true elements of logical matrix @var{nhood} or by a matrix of size
+## @var{M} by @var{N}.  The default @var{nhood} is a 3 by 3 matrix of true
+## elements.
+##
+## @example
+## @group
+## ## median filtering specifying neighborhood dimensions
+## medfilt2 (img)         # default is [3 3]
+## medfilt2 (img, [3 1])  # a 3x1 vector
+## medfilt2 (img, [5 5])  # 5 element wide square
+## @end group
 ##
-## Optional variable @var{padding} defines the padding used in augmenting 
-## the borders of @var{A}. See impad for details.
+## @group
+## ## median filtering specifying neighborhood
+## medfilt2 (img, true (5)) # same as [5 5]
+## nhood = logical ([0 1 0
+##                   1 1 1
+##                   0 1 0]);
+## medfilt2 (img, nhood)    # 3 element wide cross
+## @end group
+## @end example
 ##
-## @seealso{ordfilt2}
+## The optional variable @var{pad} defines the padding used in augmenting
+## the borders of @var{A}.  See @code{padarray} for details.
+## @seealso{ordfilt2, ordfiltn}
 ## @end deftypefn
 
-function retval = medfilt2(A, varargin)
+function retval = medfilt2 (A, varargin)
 
-padding = "zeros";
-domain = logical(ones(3,3));
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  elseif (! isimage (A))
+    error ("medfilt2: A must be a real matrix")
+  endif
+
+  ## defaults
+  padding = "zeros";
+  domain  = true (3, 3);
 
-for i=1:length(varargin)
-  a = varargin{i};
-  if(ischar(a))
-    padding = a;
-  elseif(isvector(a) && size(a) == [1, 2])
-    domain = logical(ones(a(2), a(1)));
-  elseif(ismatrix(a))
-    domain = logical(a);
-  endif
-endfor
+  for idx = 1:numel (varargin)
+    opt = varargin{idx};
+    if (ischar (opt) || isscalar (opt))
+      padding = opt;
+    elseif (isnumeric (opt) || islogical (opt))
+      ## once we have removed the ability of selecting domain with a non logical
+      ## matrix, we can use it to make this N dimensional domain = [3 3 3].
+      if (isvector (opt) && ! islogical (opt) && numel (opt) == 2)
+        domain = true (opt);
+      else
+        if (! islogical (opt))
+          persistent warned = false;
+          if (! warned)
+            warned = true;
+            warning ("medfilt2: to specify filter instead of dimensions use a matrix of logical class. This usage will be removed from future releases of the image package.");
+          endif
+        endif
+        domain = logical (opt);
+      endif
+    else
+      error ("medfilt2: unrecognized option of class %s", class (opt))
+    endif
+  endfor
 
-n = sum(sum(domain));
-if((n - 2*floor(n/2)) == 0) % n even - more work
-  nth = floor(n/2);
-  a = ordfilt2(A, nth, domain, padding);
-  b = ordfilt2(A, nth + 1, domain, padding);
-  retval = a./2 + b./2; # split into two divisions to avoid overflow on integer data
-else
-  nth = floor(n/2) + 1;
-  retval = ordfilt2(A, nth, domain, padding);
-endif
+  n = nnz (domain);
+  if ((n - 2*floor(n/2)) == 0) % n even - more work
+    nth = floor (n/2);
+    a = ordfiltn (A, nth, domain, padding);
+    b = ordfiltn (A, nth + 1, domain, padding);
+    retval = a./2 + b./2; # split into two divisions to avoid overflow on integer data
+  else
+    nth = floor (n/2) + 1;
+    retval = ordfilt2 (A, nth, domain, padding);
+  endif
 
 endfunction
 
-%!test
-%! b = [0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18];
-%! assert(medfilt2(b),[0,1,2,0;1,4,12,3;4,12,20,12;0,7,20,0]);
+%!shared b, f
+%! b = [ 0  1  2  3
+%!       1  8 12 12
+%!       4 20 24 21
+%!       7 22 25 18];
+%! f = [ 0  1  2  0
+%!       1  4 12  3
+%!       4 12 20 12
+%!       0  7 20  0];
+%!assert (medfilt2 (b), f);
+%!
+%! f = [ 0  1  2  3
+%!       1  8 12 12
+%!       4 20 24 18
+%!       4 20 24 18];
+%!assert (medfilt2 (b, true (3, 1)), f);
+%!assert (medfilt2 (b, [3 1]), f);
+%!
+%! f = [ 1  8 10 10
+%!       1  8 12 12
+%!       4 20 24 18
+%!       7 20 24 18];
+%!assert (medfilt2 (b, [3 1], 10), f);
+%!assert (medfilt2 (b, 10, [3 1]), f);
+%!
+%! f = [ 0.5  4.5  7.0  7.5
+%!       2.5 14.0 18.0 15.0
+%!       2.5 14.0 18.0 15.0
+%!       2.0 10.0 12.0  9.0];
+%!assert (medfilt2 (b, true (4, 1)), f);
+%!assert (medfilt2 (b, [4 1]), f);