changeset 11504:110b520dae68 octave-forge

strel: implement line and periodic line. Submitted by Roberto Metere <roberto@metere.it>
author carandraug
date Sat, 02 Mar 2013 15:03:38 +0000
parents 314a9c3bfaba
children c2560f01b244
files main/image/inst/@strel/strel.m
diffstat 1 files changed, 114 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/main/image/inst/@strel/strel.m	Sat Mar 02 14:38:24 2013 +0000
+++ b/main/image/inst/@strel/strel.m	Sat Mar 02 15:03:38 2013 +0000
@@ -1,4 +1,4 @@
-## Copyright (C) 2012 Roberto Metere <roberto@metere.it>
+## Copyright (C) 2012,2013 Roberto Metere <roberto@metere.it>
 ## Copyright (C) 2012 Carnë Draug <carandraug@octave.org>
 ##
 ## This program is free software; you can redistribute it and/or modify it under
@@ -59,6 +59,10 @@
 ## Create disk shaped flat structuring element.  @var{radius} must be a positive
 ## integer.
 ##
+## @deftypefnx {Function File} {} strel ("line", @var{len}, @var{deg})
+## Create line shaped flat structuring element.  @var{len} must be a positive
+## real number.  @var{deg} must be a real number.
+##
 ## @deftypefnx {Function File} {} strel ("octagon", @var{apothem})
 ## Create octagon shaped flat structuring element.  @var{apothem} must be a
 ## positive integer that specifies the distance from the origin to the sides of
@@ -69,6 +73,13 @@
 ## at the origin while the other is placed with @var{offset} in relation to the
 ## origin.  @var{offset} must then be a 2 element vector for the coordinates.
 ##
+## @deftypefnx {Function File} {} strel ("periodicline", @var{p}, @var{v})
+## Create periodic line shaped flat structuring element.  A periodic line will
+## be built with 2*@var{p}+1 points around the origin included. These points will
+## be displaced in accordance with the offset @var{v} at distances: 1*@var{v},
+## -1*@var{v}, 2*@var{v}, -2*@var{v}, ..., @var{p}*@var{v}, -@var{p}*@var{v}.
+##   Therefore @var{v} must be a 2 element vector for the coordinates.
+##
 ## @deftypefnx {Function File} {} strel ("rectangle", @var{dimensions})
 ## Creates a rectangular shaped flat structuring element.  @var{dimensions} must
 ## be a two element vector of positive integers with the number of rows and
@@ -191,8 +202,68 @@
       SE.nhood = fspecial ("disk", radius) > 0;
       SE.flat  = true;
 
-#    case "line"
-      ## TODO implement line shape
+
+    case "line"
+      if (numel (varargin) == 2)
+        linelen = varargin{1};
+        degrees = varargin{2};
+      else
+        error ("strel: a line shape needs 2 arguments");
+      endif
+      if (! (isscalar (linelen) && isnumeric (linelen) && linelen > 0))
+        error ("strel: LEN must be a positive real number");
+      elseif (! (isscalar (degrees) && isnumeric (degrees)))
+        error ("strel: DEG must be a real number");
+      endif
+
+      ## Line length are always odd, to center strel at the middle of the line.
+      ## We look it as a diameter of a circle with given slope
+      # It computes only lines with angles between 0 and 44.9999
+      deg90 = mod (degrees, 90);
+      if (deg90 > 45)
+        alpha = pi * (90 - deg90) / 180;
+      else
+        alpha = pi * deg90 / 180;
+      endif
+      ray = (linelen - 1)/2;
+
+      ## We are interested only in the discrete rectangle which contains the diameter
+      ## However we focus our attention to the bottom left quarter of the circle,
+      ## because of the central symmetry.
+      c = round (ray * cos (alpha)) + 1;
+      r = round (ray * sin (alpha)) + 1;
+
+      ## Line rasterization
+      line = false (r, c);
+      m = tan (alpha);
+      x = [1:c];
+      y = r - fix (m .* (x - 0.5));
+      indexes = sub2ind ([r c], y, x);
+      line(indexes) = true;
+
+      ## We view the result as 9 blocks.
+      # Preparing blocks
+      linestrip = line(1, 1:c - 1);
+      linerest = line(2:r, 1:c - 1);
+      z = false (r - 1, c);
+
+      # Assemblying blocks
+      SE.nhood =  vertcat (
+                    horzcat (z, linerest(end:-1:1,end:-1:1)),
+                    horzcat (linestrip, true, linestrip(end:-1:1,end:-1:1)),
+                    horzcat (linerest, z(end:-1:1,end:-1:1))
+                  );
+
+      # Rotate/transpose/flip?
+      sect = fix (mod (degrees, 180) / 45);
+      switch (sect)
+        case 1, SE.nhood = transpose (SE.nhood);
+        case 2, SE.nhood = rot90 (SE.nhood, 1);
+        case 3, SE.nhood = fliplr (SE.nhood);
+        otherwise, # do nothing
+      endswitch
+
+      SE.flat = true;
 
    case "octagon"
       if (numel (varargin) == 1)
@@ -237,7 +308,27 @@
       SE.flat = true;
 
     case "periodicline"
-      ## TODO implement periodicline shape
+      if (numel (varargin) == 2)
+        p = varargin{1};
+        v = varargin{2};
+      else
+        error ("strel: a periodic line shape needs 2 arguments");
+      endif
+      if (! is_positive_integer (p))
+        error ("strel: P must be a positive integer");
+      elseif (! ismatrix (v) || numel (v) != 2 || ! isnumeric (v))
+        error ("strel: V must be a 2 element vector");
+      elseif (any (fix (v) != v))
+        error ("strel: values of V must be integers");
+      endif
+
+      lengths  = abs (2*p*v) + 1;
+      SE.nhood = false (lengths);
+      origin   = (lengths + 1)/2;
+      for i = -p:p
+        point = i*v + origin;
+        SE.nhood(point(1), point(2)) = true;
+      endfor
 
     case "rectangle"
       if (numel (varargin) == 1)
@@ -307,6 +398,24 @@
 %!          0 1 1 1 1 1 0
 %!          0 0 0 1 0 0 0];
 %!assert (getnhood (strel ("disk", 3)), logical (shape));
+%! shape = [1 1 1];
+%!assert (getnhood (strel ("line", 3.9, 20.17)), logical (shape));
+%! shape = [0 0 1
+%!          0 1 0
+%!          1 0 0];
+%!assert (getnhood (strel ("line", 3.9, 20.18)), logical (shape));
+%! shape = [1 0 0 0 0 0 0 0 0
+%!          0 1 0 0 0 0 0 0 0
+%!          0 0 1 0 0 0 0 0 0
+%!          0 0 1 0 0 0 0 0 0
+%!          0 0 0 1 0 0 0 0 0
+%!          0 0 0 0 1 0 0 0 0
+%!          0 0 0 0 0 1 0 0 0
+%!          0 0 0 0 0 0 1 0 0
+%!          0 0 0 0 0 0 1 0 0
+%!          0 0 0 0 0 0 0 1 0
+%!          0 0 0 0 0 0 0 0 1];
+%!assert (getnhood (strel ("line", 14, 130)), logical (shape));
 %! shape = [0 0 1 1 1 0 0
 %!          0 1 1 1 1 1 0
 %!          1 1 1 1 1 1 1
@@ -359,6 +468,7 @@
 %!error strel("arbitrary", [0 0 1], "stuff")
 %!error strel("diamond", -3)
 %!error strel("disk", -3)
+%!error strel("line", 0, 45)
 %!error strel("octagon", 4)
 %!error strel("pair", [45 67 90])
 %!error strel("rectangle", 2)