changeset 905:0219144c2c21

bwlabeln.cc: make use of our new connectivity class rather than its own.
author Carnë Draug <carandraug@octave.org>
date Wed, 15 Oct 2014 15:40:59 +0100
parents dd4242ff0fa4
children 475a5a2a08cb
files src/bwlabeln.cc
diffstat 1 files changed, 29 insertions(+), 171 deletions(-) [+]
line wrap: on
line diff
--- a/src/bwlabeln.cc
+++ b/src/bwlabeln.cc
@@ -26,6 +26,9 @@
 #include <algorithm>
 #include "union-find.h++"
 
+#include "conndef.h"
+using namespace octave::image;
+
 #include "config.h"
 
 #if defined (HAVE_UNORDERED_MAP)
@@ -131,136 +134,21 @@
 //}
 
 std::set<octave_idx_type>
-populate_neighbours(const boolNDArray& conn_mask,
-                    const dim_vector& size_vec)
+populate_neighbours (const connectivity& conn, const dim_vector& padded_size)
 {
-  std::set<octave_idx_type> neighbours_idx;
-  std::set<coord> neighbours;
+  const Array<octave_idx_type> offsets = conn.offsets (padded_size);
 
-  dim_vector conn_size = conn_mask.dims ();
-  coord centre (dim_vector(conn_size.length (), 1), 1);
-  coord zero (dim_vector(conn_size.length (), 1), 0);
-  for (octave_idx_type idx = 0; idx < conn_mask.nelem (); idx++)
-    {
-      if (conn_mask(idx))
-        {
-          coord aidx = to_coord (conn_size, idx) - centre;
+  //The zero coordinates are the centre, and the negative ones
+  //are the ones reflected about the centre, and we don't need
+  //to consider those.
+  std::set<octave_idx_type> neighbours_idx;
+  for (octave_idx_type i = 0; i < offsets.numel (); i++)
+    if (offsets(i) < 0)
+      neighbours_idx.insert (offsets(i));
 
-          //The zero coordinates are the centre, and the negative ones
-          //are the ones reflected about the centre, and we don't need
-          //to consider those.
-          if( aidx == zero || neighbours.find(-aidx) != neighbours.end() )
-            continue;
-
-          neighbours.insert (aidx);
-
-          neighbours_idx.insert (coord_to_pad_idx(size_vec, aidx));
-         }
-    }
   return neighbours_idx;
 }
 
-boolNDArray
-get_mask(int N){
-  bool* mask_ptr;
-  octave_idx_type n;
-
-  static bool mask4[] = {0, 1, 0,
-                         1, 0, 1,
-                         0, 1, 0};
-
-  static bool mask8[] = {1, 1, 1,
-                         1, 0, 1,
-                         1, 1, 1};
-
-  static bool mask6[] = {0, 0, 0,
-                         0, 1, 0,
-                         0, 0, 0,
-
-                         0, 1, 0,
-                         1, 0, 1,
-                         0, 1, 0,
-
-                         0, 0, 0,
-                         0, 1, 0,
-                         0, 0, 0};
-
-  static bool mask18[] = {0, 1, 0,
-                          1, 1, 1,
-                          0, 1, 0,
-
-                          1, 1, 1,
-                          1, 0, 1,
-                          1, 1, 1,
-
-                          0, 1, 0,
-                          1, 1, 1,
-                          0, 1, 0};
-
-  static bool mask26[] = {1, 1, 1,
-                          1, 1, 1,
-                          1, 1, 1,
-
-                          1, 1, 1,
-                          1, 0, 1,
-                          1, 1, 1,
-
-                          1, 1, 1,
-                          1, 1, 1,
-                          1, 1, 1};
-
-  switch (N){
-  case 4:
-    n = 2;
-    mask_ptr = mask4;
-    break;
-  case 8:
-    n = 2;
-    mask_ptr = mask8;
-    break;
-  case 6:
-    n = 3;
-    mask_ptr = mask6;
-    break;
-  case 18:
-    n = 3;
-    mask_ptr = mask18;
-    break;
-  case 26:
-    n = 3;
-    mask_ptr = mask26;
-    break;
-  default:
-    panic_impossible ();
-  }
-
-  boolNDArray conn_mask;
-  if (n == 2)
-    {
-      conn_mask.resize (dim_vector (3, 3));
-      for (octave_idx_type i = 0; i < 9; i++)
-        conn_mask(i) = mask_ptr[i];
-
-    }
-  else
-    {
-      conn_mask.resize (dim_vector (3, 3, 3));
-      for (octave_idx_type i = 0; i < 27; i++)
-        conn_mask(i) = mask_ptr[i];
-    }
-
-  return conn_mask;
-}
-
-boolNDArray
-get_mask (const boolNDArray& BW)
-{
-  dim_vector mask_dims = BW.dims();
-  for (auto i = 0; i < mask_dims.length (); i++)
-    mask_dims(i) = 3;
-
-  return boolNDArray (mask_dims, 1);
-}
 
 octave_idx_type
 get_padded_index (octave_idx_type r,
@@ -283,12 +171,12 @@
 }
 
 static octave_value_list
-bwlabel_nd (const boolNDArray& BW, const boolNDArray& conn_mask)
+bwlabel_nd (const boolNDArray& BW, const connectivity& conn)
 {
   octave_value_list rval;
+  boolNDArray conn_mask = conn.mask;
 
-  dim_vector size_vec = BW.dims ();
-  auto neighbours = populate_neighbours(conn_mask, size_vec);
+  const dim_vector size_vec = BW.dims ();
 
   // Use temporary array with borders padded with zeros. Labels will
   // also go in here eventually.
@@ -296,6 +184,8 @@
   for (octave_idx_type j = 0; j < size_vec.length (); j++)
     padded_size(j) += 2;
 
+  auto neighbours = populate_neighbours (conn, padded_size);
+
   NDArray L (padded_size, 0);
 
   // L(2:end-1, 2:end, ..., 2:end-1) = BW
@@ -620,58 +510,26 @@
   boolNDArray BW = args(0).bool_array_value ();
   dim_vector size_vec = BW.dims ();
 
-  //Connectivity mask
-  boolNDArray conn_mask;
-  if (nargin == 2)
+  connectivity conn;
+  try
     {
-      if (args(1).is_real_scalar ())
-        {
-          double N = args(1).scalar_value ();
-          if (size_vec.length () == 2 && N != 4 && N != 8)
-            error ("bwlabeln: for 2d arrays, scalar N must be 4 or 8");
-          else if (size_vec.length () == 3 && N != 6 && N != 18 && N != 26)
-            error ("bwlabeln: for 3d arrays, scalar N must be 4 or 8");
-          else if (size_vec.length () > 3)
-            error ("bwlabeln: for higher-dimensional arrays, N must be a "
-                   "connectivity mask");
-          else
-            conn_mask = get_mask (N);
-        }
-      else if (args(1).is_numeric_type () || args(1).is_bool_type ())
-        {
-          conn_mask = args(1).bool_array_value ();
-          dim_vector conn_mask_dims = conn_mask.dims ();
-          if (conn_mask_dims.length () != size_vec.length ())
-            error ("bwlabeln: connectivity mask N must have the same "
-                   "dimensions as BW");
-          for (octave_idx_type i = 0; i < conn_mask_dims.length (); i++)
-            {
-              if (conn_mask_dims(i) != 3)
-                {
-                  error ("bwlabeln: connectivity mask N must have all "
-                         "dimensions equal to 3");
-                }
-            }
-        }
-      else
-        error ("bwlabeln: second input argument must be a real scalar "
-               "or a connectivity array");
+      conn = (nargin == 2) ? connectivity (args(1)) :
+                             connectivity (BW.ndims (), "maximal");
     }
-  else
-    // Get the maximal mask that has same number of dims as BW.
-    conn_mask = get_mask (BW);
-
-  if (error_state)
-    return rval;
+  catch (invalid_connectivity& e)
+    {
+      error ("bwlabeln: MASK %s", e.what ());
+      return octave_value ();
+    }
 
   // The implementation in bwlabel_2d is faster so use it if we can
   const octave_idx_type ndims = BW.ndims ();
-  if (ndims == 2 && boolMatrix (conn_mask) == get_mask (4))
+  if (ndims == 2 && boolMatrix (conn.mask) == connectivity (4).mask)
     rval = bwlabel_2d (BW, 4);
-  else if (ndims == 2 && boolMatrix (conn_mask) == get_mask (8))
+  else if (ndims == 2 && boolMatrix (conn.mask) == connectivity (8).mask)
     rval = bwlabel_2d (BW, 8);
   else
-    rval = bwlabel_nd (BW, conn_mask);
+    rval = bwlabel_nd (BW, conn);
 
   return rval;
 }