gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 8c5e769: New erosion and dilation operators in


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 8c5e769: New erosion and dilation operators in Arithmetic
Date: Wed, 18 Apr 2018 21:25:35 -0400 (EDT)

branch: master
commit 8c5e7692c65bea93590ec34a984dd008b14211c4
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    New erosion and dilation operators in Arithmetic
    
    These two new operators make it very convenient to play with binary images
    without having to go into the library and write your own program. So they
    were added to Arithmetic.
---
 bin/arithmetic/arithmetic.c | 114 ++++++++++++++++++++++++++++++++++----------
 bin/arithmetic/arithmetic.h |   2 +
 doc/gnuastro.texi           |  18 +++++++
 3 files changed, 108 insertions(+), 26 deletions(-)

diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index baef282..87d3a4d 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -513,54 +513,107 @@ wrapper_for_filter(struct arithmeticparams *p, char 
*token, int operator)
 /***************************************************************/
 /*************            Other functions          *************/
 /***************************************************************/
-static void
-arithmetic_connected_components(struct arithmeticparams *p, char *token)
+static int
+arithmetic_binary_conn_sanity_checks(gal_data_t *in, gal_data_t *conn,
+                                     char *operator)
 {
   int conn_int;
-  gal_data_t *out=NULL;
-
-  /* Pop the two necessary operands. */
-  gal_data_t *conn = operands_pop(p, token);
-  gal_data_t *in   = operands_pop(p, token);
 
   /* Do proper sanity checks on `conn'. */
   if(conn->size!=1)
-    error(EXIT_FAILURE, 0, "the first popped operand to "
-          "`connected-components' must be a single number. However, it has "
-          "%zu elements", conn->size);
+    error(EXIT_FAILURE, 0, "the first popped operand to `%s' must be a "
+          "single number. However, it has %zu elements", operator,
+          conn->size);
   if(conn->type==GAL_TYPE_FLOAT32 || conn->type==GAL_TYPE_FLOAT64)
-    error(EXIT_FAILURE, 0, "the first popped operand to "
-          "`connected-components' is the connectivity (a value between 1 "
-          "and the number of dimensions) therefore, it must NOT be a "
-          "floating point");
+    error(EXIT_FAILURE, 0, "the first popped operand to `%s' is the "
+          "connectivity (a value between 1 and the number of dimensions) "
+          "therefore, it must NOT be a floating point", operator);
 
   /* Convert the connectivity value to a 32-bit integer and read it in and
      make sure it is not larger than the number of dimensions. */
   conn=gal_data_copy_to_new_type_free(conn, GAL_TYPE_INT32);
   conn_int = *((int32_t *)(conn->array));
   if(conn_int>in->ndim)
-    error(EXIT_FAILURE, 0, "the first popped operand of "
-          "`connected-components' (%d) is larger than the number of "
-          "dimensions in the second-popped operand (%zu)", conn_int,
-          in->ndim);
+    error(EXIT_FAILURE, 0, "the first popped operand of `%s' (%d) is "
+          "larger than the number of dimensions in the second-popped "
+          "operand (%zu)", operator, conn_int, in->ndim);
 
   /* Make sure the array has an unsigned 8-bit type. */
   if(in->type!=GAL_TYPE_UINT8)
-    error(EXIT_FAILURE, 0, "the second popped operand of "
-          "`connected-components' doesn't have an 8-bit unsigned "
-          "integer type. It must be a binary dataset (only being equal "
-          "to zero is checked). You can use the `uint8' operator to "
-          "convert the type of this operand.");
+    error(EXIT_FAILURE, 0, "the second popped operand of `%s' doesn't "
+          "have an 8-bit unsigned integer type. It must be a binary "
+          "dataset (only being equal to zero is checked). You can use "
+          "the `uint8' operator for type conversion", operator);
+
+  /* Clean up and return the integer value of `conn'. */
+  gal_data_free(conn);
+  return conn_int;
+}
+
+
+
+
+
+static void
+arithmetic_erode_dilate(struct arithmeticparams *p, char *token, int op)
+{
+  int conn_int;
+
+  /* Pop the two necessary operands. */
+  gal_data_t *conn = operands_pop(p, token);
+  gal_data_t *in   = operands_pop(p, token);
+
+  /* Do the sanity checks and  */
+  switch(op)
+    {
+    case ARITHMETIC_OP_ERODE:
+      conn_int=arithmetic_binary_conn_sanity_checks(in, conn, "erode");
+      gal_binary_erode(in, 1, conn_int, 1);
+      break;
+
+    case ARITHMETIC_OP_DILATE:
+      conn_int=arithmetic_binary_conn_sanity_checks(in, conn, "dilate");
+      gal_binary_dilate(in, 1, conn_int, 1);
+      break;
+
+    default:
+      error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
+            "problem. The operator code %d not recognized", __func__,
+            PACKAGE_BUGREPORT, op);
+    }
+
+  /* Push the result onto the stack. */
+  operands_add(p, NULL, in);
+
+  /* Recall that`conn' was freed in the sanity check. */
+}
+
+
+
+
+
+static void
+arithmetic_connected_components(struct arithmeticparams *p, char *token)
+{
+  int conn_int;
+  gal_data_t *out=NULL;
+
+  /* Pop the two necessary operands. */
+  gal_data_t *conn = operands_pop(p, token);
+  gal_data_t *in   = operands_pop(p, token);
+
+  /* Basic sanity checks. */
+  conn_int=arithmetic_binary_conn_sanity_checks(in, conn,
+                                                "connected-components");
 
   /* Do the connected components labeling. */
-  gal_binary_connected_components(in, &out, 1);
+  gal_binary_connected_components(in, &out, conn_int);
 
   /* Push the result onto the stack. */
   operands_add(p, NULL, out);
 
-  /* Clean up. */
+  /* Clean up (`conn' was freed in the sanity check). */
   gal_data_free(in);
-  gal_data_free(conn);
 }
 
 
@@ -778,6 +831,10 @@ reversepolish(struct arithmeticparams *p)
             { op=ARITHMETIC_OP_FILTER_SIGCLIP_MEAN;   nop=0;  }
           else if (!strcmp(token->v, "filter-sigclip-median"))
             { op=ARITHMETIC_OP_FILTER_SIGCLIP_MEDIAN; nop=0;  }
+          else if (!strcmp(token->v, "erode"))
+            { op=ARITHMETIC_OP_ERODE;                 nop=0;  }
+          else if (!strcmp(token->v, "dilate"))
+            { op=ARITHMETIC_OP_DILATE;                nop=0;  }
           else if (!strcmp(token->v, "connected-components"))
             { op=ARITHMETIC_OP_CONNECTED_COMPONENTS;  nop=0;  }
           else if (!strcmp(token->v, "invert"))
@@ -856,6 +913,11 @@ reversepolish(struct arithmeticparams *p)
                   wrapper_for_filter(p, token->v, op);
                   break;
 
+                case ARITHMETIC_OP_ERODE:
+                case ARITHMETIC_OP_DILATE:
+                  arithmetic_erode_dilate(p, token->v, op);
+                  break;
+
                 case ARITHMETIC_OP_CONNECTED_COMPONENTS:
                   arithmetic_connected_components(p, token->v);
                   break;
diff --git a/bin/arithmetic/arithmetic.h b/bin/arithmetic/arithmetic.h
index 59b2170..fcf48d1 100644
--- a/bin/arithmetic/arithmetic.h
+++ b/bin/arithmetic/arithmetic.h
@@ -35,6 +35,8 @@ enum arithmetic_prog_operators
   ARITHMETIC_OP_FILTER_MEAN,
   ARITHMETIC_OP_FILTER_SIGCLIP_MEAN,
   ARITHMETIC_OP_FILTER_SIGCLIP_MEDIAN,
+  ARITHMETIC_OP_ERODE,
+  ARITHMETIC_OP_DILATE,
   ARITHMETIC_OP_CONNECTED_COMPONENTS,
   ARITHMETIC_OP_INVERT,
 };
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index e99e208..1ecf14a 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -10193,6 +10193,24 @@ If your input dataset doesn't have a binary type, but 
you know all its
 values are 0 or 1, you can use the @code{uint8} operator (below) to convert
 it to binary.
 
address@hidden erode
address@hidden Erosion
+Erode the foreground (non-zero) pixels of the input dataset (second popped
+operand). The first popped operand is the connectivity (see description in
address@hidden). Erosion is simply a flipping of all
+foreground pixels (to background) that are ``touching'' background
+pixels. ``Touching'' is defined by the connectivity. In effect, this carves
+off the outer borders of the foreground.
+
address@hidden dilate
address@hidden Dilation
+Dilate the foreground (non-zero) pixels of the input dataset (second popped
+operand). The first popped operand is the connectivity (see description in
address@hidden). Erosion is simply a flipping of all
+background pixels (to foreground) that are ``touching'' foreground
+pixels. ``Touching'' is defined by the connectivity. In effect, this
+expands the outer borders of the foreground.
+
 @item invert
 Invert an unsigned integer dataset. This is the only operator that ignores
 blank values (which are set to be the maximum values in the unsigned



reply via email to

[Prev in Thread] Current Thread [Next in Thread]