changeset 11324:b506e83e04b2 octave-forge

imerode: deal with strel objects * accept strel objects * matlab compatibility, changed input check * if image is bw (logical or not), use fastest method * commented grayscale since it's not working * more tests
author carandraug
date Wed, 26 Dec 2012 00:19:26 +0000
parents 852bd046f230
children e93db158231a
files main/image/NEWS main/image/inst/imerode.m
diffstat 2 files changed, 60 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/main/image/NEWS	Tue Dec 25 23:20:32 2012 +0000
+++ b/main/image/NEWS	Wed Dec 26 00:19:26 2012 +0000
@@ -20,6 +20,11 @@
 
  ** The option to create poisson noise to an image has been added to `imnoise'. 
 
+ ** With the addition of the strel class, the following functions are now able
+    to handle strel objects:
+
+      imerode
+
 Summary of important user-visible changes for image 2.0.0:
 -------------------------------------------------------------------
 
--- a/main/image/inst/imerode.m	Tue Dec 25 23:20:32 2012 +0000
+++ b/main/image/inst/imerode.m	Wed Dec 26 00:19:26 2012 +0000
@@ -16,50 +16,80 @@
 ## this program; if not, see <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{B} =} imerode (@var{A}, @var{se})
-## Perform morphological erosion on a given image.
+## @deftypefn {Function File} {@var{im2} =} imerode (@var{im}, @var{se})
+## Perform morphological erosion on image.
 ##
-## The image @var{A} must be a grayscale or binary image, and @var{se} a
-## structuring element. Both must have the same class, e.g., if @var{A} is a
-## logical matrix, @var{se} must also be logical. Note that the erosion
-## algorithm is different for each class, being much faster for logical
-## matrices. As such, if you have a binary matrix, you should use @code{logical}
-## first. This will also reduce the memory usage of your code.
+## The image @var{im} must be a black and white image.
+##
+## @var{se} is the structuring element used for the erosion.  It can either be
+## a matrix of 0 and 1, or a strel object.
 ##
 ## The center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
 ##
 ## Pixels outside the image are considered to be 0.
 ##
-## @seealso{imdilate, imopen, imclose}
+## @seealso{imdilate, imopen, imclose, strel}
 ## @end deftypefn
 
-function retval = imerode(im, se)
-  ## Checkinput
+## TODO: we need to get grayscale erosion working again.
+
+function im = imerode (im, se)
+
   if (nargin != 2)
     print_usage();
   endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imerode: first input argument must be a real matrix");
-  elseif (!ismatrix(se) || !isreal(se))
-    error("imerode: second input argument must be a real matrix");
-  elseif ( !strcmp(class(im), class(se)) )
-    error("imerode: image and structuring element must have the same class");
+
+  ## it's easier to create a strel object than to have conditions later on,
+  ## specially once we implement structuring element decomposition
+  if (! isa (se, "strel"))
+    se = strel ("arbitrary", se);
   endif
 
-  ## Perform filtering
-  ## If image is binary/logical, try to use filter2 (much faster)
-  if (islogical(im))
-    thr     = sum(se(:));
-    retval  = filter2(se,im) == thr;
+  cl = class (im);
+  if (isbw (im, "non-logical"))
+    se = getnhood (se);
+    im = filter2 (se, im) == nnz (se);
+    ## once we do implement getsequence for strel objects we should do:
+#    seq = getsequence (se);
+#    for ii = 1:numel (seq)
+#      cse = getnhood (seq(ii));
+#      im  = filter2 (cse, im) == nnz (cse);
+#    endfor
+
+  elseif (isgray (im))
+    error ("imerode: grayscale erosion not yet implemented");
+    ## the following code used to do this but is incorrect (checked with ImageJ)
+    ## im = ordfiltn (im, 1, se, 0);
   else
-    retval  = ordfiltn(im, 1, se, 0);
+    error("imerode: IM must be a grayscale or black and white matrix");
   endif
 
+  ## we return image on same class as input
+  im = cast (im, cl);
 endfunction
 
 %!demo
 %! imerode(ones(5,5),ones(3,3))
 %! % creates a zeros border around ones.
 
-%!assert(imerode(eye(3),[1])==eye(3));                                           # using [1] as a mask returns the same value
-%!assert(imerode([0,1,0;1,1,1;0,1,0],[0,0,0;0,0,1;0,1,1])==[1,0,0;0,0,0;0,0,0]); # check if it works with non-symmetric SE
+%!assert (imerode (eye (3), [1]), eye (3)); # using [1] as a mask returns the same value
+%!assert (imerode ([0 1 0; 1 1 1;0 1 0], [0 0 0; 0 0 1; 0 1 1]), [1 0 0; 0 0 0; 0 0 0]);
+
+%!shared im, se, out
+%! im = [0 0 0 0 0 0 0
+%!       0 0 1 0 1 0 0
+%!       0 0 1 1 0 1 0
+%!       0 0 1 1 1 0 0
+%!       0 0 0 0 0 0 0];
+%! se = [0 0 0
+%!       0 1 0
+%!       0 1 1];
+%! out = [0 0 0 0 0 0 0
+%!        0 0 1 0 0 0 0
+%!        0 0 1 1 0 0 0
+%!        0 0 0 0 0 0 0
+%!        0 0 0 0 0 0 0];
+%!assert (imerode (im, se), out);
+%!assert (imerode (logical (im), se), logical (out));
+%!assert (imerode (im, logical (se)), out);
+%!assert (imerode (logical (im), logical (se)), logical (out));