Mercurial > forge
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);