[GRASS-SVN] r68482 - grass/trunk/imagery/i.segment
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat May 21 14:32:57 PDT 2016
Author: mmetz
Date: 2016-05-21 14:32:57 -0700 (Sat, 21 May 2016)
New Revision: 68482
Modified:
grass/trunk/imagery/i.segment/create_isegs.c
grass/trunk/imagery/i.segment/iseg.h
grass/trunk/imagery/i.segment/mean_shift.c
grass/trunk/imagery/i.segment/parse_args.c
grass/trunk/imagery/i.segment/region_growing.c
Log:
i.segment: more refactoring
Modified: grass/trunk/imagery/i.segment/create_isegs.c
===================================================================
--- grass/trunk/imagery/i.segment/create_isegs.c 2016-05-21 21:31:15 UTC (rev 68481)
+++ grass/trunk/imagery/i.segment/create_isegs.c 2016-05-21 21:32:57 UTC (rev 68482)
@@ -23,7 +23,7 @@
if (globals->bounds_map == NULL) {
/* just one time through loop */
- successflag = globals->method(globals);
+ successflag = globals->method_fn(globals);
}
else {
/* outer processing loop for polygon constraints */
@@ -70,7 +70,7 @@
globals->col_max++;
if (have_bound)
- successflag = globals->method(globals);
+ successflag = globals->method_fn(globals);
} /* end outer loop for processing polygons */
/* restore NULL flag */
@@ -82,8 +82,114 @@
FLAG_SET(globals->null_flag, row, col);
}
}
-
}
return successflag;
}
+
+void find_four_neighbors(int p_row, int p_col,
+ int neighbors[8][2])
+{
+ /* north */
+ neighbors[0][0] = p_row - 1;
+ neighbors[0][1] = p_col;
+
+ /* east */
+ neighbors[1][0] = p_row;
+ neighbors[1][1] = p_col + 1;
+
+ /* south */
+ neighbors[2][0] = p_row + 1;
+ neighbors[2][1] = p_col;
+
+ /* west */
+ neighbors[3][0] = p_row;
+ neighbors[3][1] = p_col - 1;
+
+ return;
+}
+
+void find_eight_neighbors(int p_row, int p_col,
+ int neighbors[8][2])
+{
+ /* get the 4 orthogonal neighbors */
+ find_four_neighbors(p_row, p_col, neighbors);
+
+ /* get the 4 diagonal neighbors */
+ /* north-west */
+ neighbors[4][0] = p_row - 1;
+ neighbors[4][1] = p_col - 1;
+
+ /* north-east */
+ neighbors[5][0] = p_row - 1;
+ neighbors[5][1] = p_col + 1;
+
+ /* south-west */
+ neighbors[6][0] = p_row + 1;
+ neighbors[6][1] = p_col - 1;
+
+ /* south-east */
+ neighbors[7][0] = p_row + 1;
+ neighbors[7][1] = p_col + 1;
+
+ return;
+}
+
+/* similarity / distance between two points based on their input raster values */
+/* assumes first point values already saved in files->bands_seg - only run Segment_get once for that value... */
+/* TODO: Segment_get already happened for a[] values in the main function. Could remove a[] from these parameters */
+double calculate_euclidean_similarity(struct ngbr_stats *Ri,
+ struct ngbr_stats *Rk,
+ struct globals *globals)
+{
+ double val = 0., diff;
+ int n = globals->nbands - 1;
+
+ /* squared euclidean distance, sum the square differences for each dimension */
+ do {
+ diff = Ri->mean[n] - Rk->mean[n];
+
+ val += diff * diff;
+ } while (n--);
+
+ /* the return value should always be in the range 0 - 1 */
+ if (val <= 0)
+ return 0.;
+
+ val /= globals->max_diff;
+
+#ifdef _OR_SHAPE_
+ if (globals->shape_weight < 1)
+ val = val * globals->shape_weight + (1 - globals->shape_weight) *
+ calculate_shape(rsi, rsk, nshared, globals);
+#endif
+
+ return val;
+}
+
+double calculate_manhattan_similarity(struct ngbr_stats *Ri,
+ struct ngbr_stats *Rk,
+ struct globals *globals)
+{
+ double val = 0.;
+ int n = globals->nbands - 1;
+
+ /* squared manhattan distance, sum the differences for each dimension */
+ do {
+ val += Ri->mean[n] - Rk->mean[n];
+ } while (n--);
+
+ /* the return value should always be in the range 0 - 1 */
+ if (val <= 0)
+ return 0.;
+
+ val /= globals->max_diff;
+
+#ifdef _OR_SHAPE_
+ if (globals->shape_weight < 1)
+ val = val * globals->shape_weight + (1 - globals->shape_weight) *
+ calculate_shape(rsi, rsk, nshared, globals);
+#endif
+
+ return val;
+}
Modified: grass/trunk/imagery/i.segment/iseg.h
===================================================================
--- grass/trunk/imagery/i.segment/iseg.h 2016-05-21 21:31:15 UTC (rev 68481)
+++ grass/trunk/imagery/i.segment/iseg.h 2016-05-21 21:32:57 UTC (rev 68482)
@@ -19,6 +19,10 @@
/* #def _OR_SHAPE_ */
+/* methods */
+#define ORM_RG 1 /* region growing */
+#define ORM_MS 1 /* mean shift */
+#define ORM_WS 1 /* watershed */
/* row/col list */
struct rc
@@ -41,7 +45,8 @@
char *image_group;
int weighted; /* 0 if false/not selected, so we should scale input.
* 1 if the scaling should be skipped */
- int (*method)(); /* Segmentation method function */
+ int method; /* Segmentation method code */
+ int (*method_fn)(); /* Segmentation method function */
int nn; /* number of neighbors, 4 or 8 */
double max_diff; /* max possible difference */
double alpha; /* similarity threshold */
Modified: grass/trunk/imagery/i.segment/mean_shift.c
===================================================================
--- grass/trunk/imagery/i.segment/mean_shift.c 2016-05-21 21:31:15 UTC (rev 68481)
+++ grass/trunk/imagery/i.segment/mean_shift.c 2016-05-21 21:32:57 UTC (rev 68482)
@@ -13,10 +13,102 @@
#include <grass/rbtree.h> /* Red Black Tree library functions */
#include "iseg.h"
+/* standard gauss funtion:
+ * a * exp(-(x - m)^2 / (2 * stddev^2)
+ * a is not needed because the sum of weights is calculated for each
+ * sampling window
+ * (x - m)^2 is the squared difference = diff2
+ * stddev^2 is the variance
+ * this code can be further simplified, e.g. by supplying 2 * var instead
+ * of var
+ *
+ * the standard deviation is the bandwidth
+ * */
+
+static double gauss_kernel(double diff2, double var)
+{
+ return exp(-diff2 / (2 * var));
+}
+
+
int mean_shift(struct globals *globals)
{
+ int row, col, t;
+ int n_changes;
+ double alpha2;
+ struct ngbr_stats Rin, Rout;
+ double diff2;
+
G_fatal_error(_("Mean shift is not yet implemented"));
+ return FALSE;
+
+
+ Rin.mean = G_malloc(globals->datasize);
+ Rout.mean = G_malloc(globals->datasize);
+
+ /* TODO: need another segment structure holding output
+ * for mean shift, output of the previous iteration becomes input of the next iteration
+ * initially, input and output are original band values */
+
+ alpha2 = globals->alpha * globals->alpha;
- return FALSE;
+ t = 0;
+ n_changes = 1;
+ while (t < globals->end_t && n_changes > 0) {
+
+ G_message(_("Processing pass %d..."), ++t);
+
+ n_changes = 0;
+ globals->candidate_count = 0;
+ flag_clear_all(globals->candidate_flag);
+
+ /* Set candidate flag to true/1 for all non-NULL cells */
+ for (row = globals->row_min; row < globals->row_max; row++) {
+ for (col = globals->col_min; col < globals->col_max; col++) {
+ if (!(FLAG_GET(globals->null_flag, row, col))) {
+
+ FLAG_SET(globals->candidate_flag, row, col);
+ globals->candidate_count++;
+ }
+ }
+ }
+
+ G_debug(4, "Starting to process %ld candidate cells",
+ globals->candidate_count);
+
+ /*process candidate cells */
+ G_percent_reset();
+ for (row = globals->row_min; row < globals->row_max; row++) {
+ G_percent(row - globals->row_min,
+ globals->row_max - globals->row_min, 4);
+ for (col = globals->col_min; col < globals->col_max; col++) {
+ if (!(FLAG_GET(globals->candidate_flag, row, col)))
+ continue;
+
+ /* get current band values */
+ Segment_get(&globals->bands_seg, (void *)Rin.mean,
+ row, col);
+
+ /* adapt initial spatial and range bandwiths */
+
+ /* calculate new band values */
+
+ /* if the squared difference between old and new band values
+ * is larger than alpha2, then increase n_changes */
+
+ diff2 = (globals->calculate_similarity)(&Rin, &Rout, globals);
+ if (diff2 > alpha2)
+ n_changes++;
+ }
+ }
+ }
+ if (n_changes > 1)
+ G_message(_("Mean shift stopped at %d due to reaching max iteration limit, more changes may be possible"), t);
+ else
+ G_message(_("Mean shift converged after %d iterations"), t);
+
+ /* identify connected components */
+
+ return TRUE;
}
Modified: grass/trunk/imagery/i.segment/parse_args.c
===================================================================
--- grass/trunk/imagery/i.segment/parse_args.c 2016-05-21 21:31:15 UTC (rev 68481)
+++ grass/trunk/imagery/i.segment/parse_args.c 2016-05-21 21:32:57 UTC (rev 68482)
@@ -152,13 +152,19 @@
if (globals->alpha <= 0 || globals->alpha >= 1)
G_fatal_error(_("Threshold should be > 0 and < 1"));
- /* segmentation methods: 1 = region growing */
- if (strcmp(method->answer, "region_growing") == 0)
- globals->method = region_growing;
- else if (strcmp(method->answer, "mean_shift") == 0)
- globals->method = mean_shift;
- else if (strcmp(method->answer, "watershed") == 0)
- globals->method = watershed;
+ /* segmentation methods */
+ if (strcmp(method->answer, "region_growing") == 0) {
+ globals->method = ORM_RG;
+ globals->method_fn = region_growing;
+ }
+ else if (strcmp(method->answer, "mean_shift") == 0) {
+ globals->method = ORM_MS;
+ globals->method_fn = mean_shift;
+ }
+ else if (strcmp(method->answer, "watershed") == 0) {
+ globals->method = ORM_WS;
+ globals->method_fn = watershed;
+ }
else
G_fatal_error(_("Unable to assign segmentation method"));
Modified: grass/trunk/imagery/i.segment/region_growing.c
===================================================================
--- grass/trunk/imagery/i.segment/region_growing.c 2016-05-21 21:31:15 UTC (rev 68481)
+++ grass/trunk/imagery/i.segment/region_growing.c 2016-05-21 21:32:57 UTC (rev 68482)
@@ -742,113 +742,6 @@
return n_ngbrs;
}
-void find_four_neighbors(int p_row, int p_col,
- int neighbors[8][2])
-{
- /* north */
- neighbors[0][0] = p_row - 1;
- neighbors[0][1] = p_col;
-
- /* east */
- neighbors[1][0] = p_row;
- neighbors[1][1] = p_col + 1;
-
- /* south */
- neighbors[2][0] = p_row + 1;
- neighbors[2][1] = p_col;
-
- /* west */
- neighbors[3][0] = p_row;
- neighbors[3][1] = p_col - 1;
-
- return;
-}
-
-void find_eight_neighbors(int p_row, int p_col,
- int neighbors[8][2])
-{
- /* get the 4 orthogonal neighbors */
- find_four_neighbors(p_row, p_col, neighbors);
-
- /* get the 4 diagonal neighbors */
- /* north-west */
- neighbors[4][0] = p_row - 1;
- neighbors[4][1] = p_col - 1;
-
- /* north-east */
- neighbors[5][0] = p_row - 1;
- neighbors[5][1] = p_col + 1;
-
- /* south-west */
- neighbors[6][0] = p_row + 1;
- neighbors[6][1] = p_col - 1;
-
- /* south-east */
- neighbors[7][0] = p_row + 1;
- neighbors[7][1] = p_col + 1;
-
- return;
-}
-
-/* similarity / distance between two points based on their input raster values */
-/* assumes first point values already saved in files->bands_seg - only run Segment_get once for that value... */
-/* TODO: Segment_get already happened for a[] values in the main function. Could remove a[] from these parameters */
-double calculate_euclidean_similarity(struct ngbr_stats *Ri,
- struct ngbr_stats *Rk,
- struct globals *globals)
-{
- double val = 0., diff;
- int n = globals->nbands - 1;
-
- /* squared euclidean distance, sum the square differences for each dimension */
- do {
- diff = Ri->mean[n] - Rk->mean[n];
-
- val += diff * diff;
- } while (n--);
-
- /* the return value should always be in the range 0 - 1 */
- if (val <= 0)
- return 0.;
-
- val /= globals->max_diff;
-
-#ifdef _OR_SHAPE_
- if (globals->shape_weight < 1)
- val = val * globals->shape_weight + (1 - globals->shape_weight) *
- calculate_shape(rsi, rsk, nshared, globals);
-#endif
-
- return val;
-}
-
-double calculate_manhattan_similarity(struct ngbr_stats *Ri,
- struct ngbr_stats *Rk,
- struct globals *globals)
-{
- double val = 0.;
- int n = globals->nbands - 1;
-
- /* squared manhattan distance, sum the differences for each dimension */
- do {
- val += Ri->mean[n] - Rk->mean[n];
- } while (n--);
-
- /* the return value should always be in the range 0 - 1 */
- if (val <= 0)
- return 0.;
-
- val /= globals->max_diff;
-
-#ifdef _OR_SHAPE_
- if (globals->shape_weight < 1)
- val = val * globals->shape_weight + (1 - globals->shape_weight) *
- calculate_shape(rsi, rsk, nshared, globals);
-#endif
-
- return val;
-}
-
double calculate_shape(struct reg_stats *rsi, struct reg_stats *rsk,
int nshared, struct globals *globals)
{
More information about the grass-commit
mailing list