[GRASS-SVN] r70460 - grass-addons/grass7/imagery/i.superpixels.slic

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Jan 30 14:13:45 PST 2017


Author: mmetz
Date: 2017-01-30 14:13:45 -0800 (Mon, 30 Jan 2017)
New Revision: 70460

Modified:
   grass-addons/grass7/imagery/i.superpixels.slic/Makefile
   grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html
   grass-addons/grass7/imagery/i.superpixels.slic/main.c
   grass-addons/grass7/imagery/i.superpixels.slic/minsize.c
Log:
i.superpixels.slic: use segment lib, update manual

Modified: grass-addons/grass7/imagery/i.superpixels.slic/Makefile
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/Makefile	2017-01-30 20:34:57 UTC (rev 70459)
+++ grass-addons/grass7/imagery/i.superpixels.slic/Makefile	2017-01-30 22:13:45 UTC (rev 70460)
@@ -4,8 +4,8 @@
 
 PGM = i.superpixels.slic
 
-LIBES = $(IMAGERYLIB) $(RASTERLIB) $(GISLIB)
-DEPENDENCIES = $(IMAGERYDEP) $(RASTERDEP) $(GISDEP)
+LIBES = $(IMAGERYLIB) $(RASTERLIB) $(SEGMENTLIB) $(GISLIB)
+DEPENDENCIES = $(IMAGERYDEP) $(RASTERDEP) $(SEGMENTDEP) $(GISDEP)
 
 include $(MODULE_TOPDIR)/include/Make/Module.make
 

Modified: grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html	2017-01-30 20:34:57 UTC (rev 70459)
+++ grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html	2017-01-30 22:13:45 UTC (rev 70460)
@@ -1,24 +1,68 @@
-<H2>DESCRIPTION</H2>
+<h2>DESCRIPTION</h2>
 
-<EM>i.superpixels.slic</EM> performs superpixel segmentation
+<em>i.superpixels.slic</em> performs superpixel segmentation using a 
+k means method. The number of superpixels is determined either with the 
+<b>k</b> option (number of superpixels) or with the <b>step</b> option 
+(distance between initial super pixel centers).
+<p>
+The <b>co</b> option controls the compactness of the resulting 
+superpixels. A larger <b>co</b> value will cause spatially more 
+compact, but also spectrally more heterogeneous superpixels. This is 
+the most important parameter of the module. A reasonable value should 
+be determined for small test regions before applying the module to a 
+large region.
 
-<H2>NOTES</H2>
-
-This code performs superpixel segmentation as explained in the paper:
-"SLIC Superpixels", Radhakrishna Achanta, Appu Shaji,  Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk.
-EPFL Technical Report no. 149300, June 2010. 
-
+<h2>NOTES</h2>
+In each iteration, the assigned of pixels to superpixels and the 
+superpixels themselves (spatial and spectral means) are updated until 
+either the maximum number of iterations is reached or until the 
+superpixels do not change any more. More iterations will provide better 
+results but will increase processing time. Recommended are about 500 
+iterations for best results (stabilized superpixels).
+<p> 
+If a minimum segment size of 2 or larger is given with the <b>min</b> 
+parameter, segments with a smaller pixel count will be merged with 
+their most similar neighbor.
 <p>
+If the <b>-n</b> flag is used, the spectral distance of a pixel to a 
+given superpixel is divided by the maximum previously observed spectral 
+distance to that superpixel. This is the so-called <em>SLIC0</em> (SLIC 
+zero) method. After each iteration, the largest spectral distance is 
+determined for each superpixel separately. In the next iteration, 
+spectral distances of pixels to superpixels are normalized by the 
+largest spectral distance of the current superpixel.
+<p>
+That means that more heterogeneous superpixels have a larger maximum 
+spectral distance. For a given pixel, the normalized spectral distance 
+will be smaller for a more heterogeneous superpixel than for a more 
+homogeneous superpixel. This favours more heterogeneous superpixels 
+which can steal pixels from more homogeneous superpixels even if the 
+not normalized spectral distance of a pixel to a homogeneous superpixel 
+is smaller than to a heterogeneous pixel. As a consequence, 
+heterogeneous superpixels can become larger and and even more 
+heterogeneous. This effect becomes stronger with larger differences in 
+the spectral homogeneity of neighboring superpixels.
 
-<H2>TODO</H2>
+<h2>REFERENCES</h2>
+"SLIC Superpixels", Radhakrishna Achanta, Appu Shaji,  Kevin Smith, 
+Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk. EPFL Technical 
+Report no. 149300, June 2010. 
 
-<H2>SEE ALSO</H2>
+<h2>SEE ALSO</h2>
+<em>
+<a href="g.gui.iclass.html">g.gui.iclass</a>,
+<a href="i.group.html">i.group</a>, 
+<a href="i.segment.html">i.segment</a>, 
+<a href="i.maxlik.html">i.maxlik</a>, 
+<a href="i.smap.html">i.smap</a>, 
+<a href="r.kappa.html">r.kappa</a>
+</em>
 
-<H2>AUTHORS</H2>
+<h2>AUTHORS</h2>
 
-Rashad Kanavath, India <BR>
+Rashad Kanavath, India <br>
+Markus Metz
 
-
 <p>
 <i>Last changed: $Date$</i>
 

Modified: grass-addons/grass7/imagery/i.superpixels.slic/main.c
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/main.c	2017-01-30 20:34:57 UTC (rev 70459)
+++ grass-addons/grass7/imagery/i.superpixels.slic/main.c	2017-01-30 22:13:45 UTC (rev 70460)
@@ -17,17 +17,14 @@
  *
  *****************************************************************************/
 
-#include <grass/config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
 #include <grass/gis.h>
 #include <grass/raster.h>
+#include <grass/segment.h>	
+#include <grass/imagery.h>
 #include <grass/glocale.h>
-#include <grass/imagery.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <limits.h>
-#include <float.h>
 
 #ifndef MAX
 #define MAX(x,y) ((x) > (y) ? (x) : (y))
@@ -36,11 +33,11 @@
 #define MIN(x,y) ((x) < (y) ? (x) : (y))
 #endif
 
-int SLIC_EnforceLabelConnectivity(int **labels, int ncols, int nrows,
-				   int **nlabels, int minsize);
+int SLIC_EnforceLabelConnectivity(SEGMENT *k_seg, int ncols, int nrows,
+				  SEGMENT *nk_seg, int minsize);
 
-int merge_small_clumps(DCELL ***pdata, int nbands,
-                       int **klabels, int nlabels,
+int merge_small_clumps(SEGMENT *bands_seg, int nbands,
+                       SEGMENT *k_seg, int nlabels,
                        int diag, int minsize);
 
 int main(int argc, char *argv[])
@@ -48,7 +45,7 @@
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct Option *opt_grp;		/* imagery group input option */
     struct Option *opt_iteration, *opt_super_pixels, *opt_step, 
-                  *opt_compactness, *opt_minsize;
+                  *opt_compactness, *opt_minsize, *opt_mem;
     struct Option *opt_out;	/* option for output */
     struct Flag *flag_n;
 
@@ -62,6 +59,9 @@
     CELL *obuf;
     struct Colors colors;
     struct History hist;
+    
+    int nseg;
+    double segs_mb, k_mb;
 
     int n_iterations, n_super_pixels, numk, numlabels, slic0;
     int nrows, ncols, row, col, b, k;
@@ -70,9 +70,10 @@
     int superpixelsize, minsize;
     int step;
     int offset;
-    DCELL ***pdata;
-    int **klabels, **nlabels, schange;
-    double ***dists;
+    DCELL *pdata;
+    double *dists;
+    SEGMENT bands_seg, k_seg, nk_seg, dist_seg;
+    int schange;
 
     double xerrperstrip, yerrperstrip;
     int xstrips, ystrips, xoff, yoff, xerr, yerr;
@@ -126,15 +127,16 @@
     opt_step->key = "step";
     opt_step->type = TYPE_INTEGER;
     opt_step->required = NO;
-    opt_step->label = _("Step size between super pixels");
-    opt_step->description = _("Step size has precedence of number of super pixels");
+    opt_step->label = _("Distance (number of cells) between initial super pixel centers");
+    opt_step->description = _("A step size > 0 overrides the number of super pixels");
     opt_step->answer = "0";
 
     opt_compactness = G_define_option();
     opt_compactness->key = "co";
     opt_compactness->type = TYPE_DOUBLE;
     opt_compactness->required = NO;
-    opt_compactness->description = _("Compactness");
+    opt_compactness->label = _("Compactness");
+    opt_compactness->description = _("A larger value causes more compact superpixels");
     opt_compactness->answer = "1";
 
     opt_minsize = G_define_option();
@@ -144,10 +146,17 @@
     opt_minsize->description = _("Minimum superpixel size");
     opt_minsize->answer = "1";
 
+    opt_mem = G_define_option();
+    opt_mem->key = "memory";
+    opt_mem->type = TYPE_INTEGER;
+    opt_mem->required = NO;
+    opt_mem->answer = "300";
+    opt_mem->description = _("Memory in MB");
+
     flag_n = G_define_flag();
     flag_n->key = 'n';
     flag_n->label = _("Normalize spectral distances");
-    flag_n->description = _("Equvivalent to SLIC zero (SCLI0)");
+    flag_n->description = _("Equvivalent to SLIC zero (SLIC0)");
 
 
     /* options and flags parser */
@@ -217,6 +226,17 @@
 	}
     }
 
+    segs_mb = 300;
+    if (opt_mem->answer) {
+	int mb = 300;
+
+	if (sscanf(opt_mem->answer, "%d", &mb) != 1) {
+	    G_fatal_error(_("Illegal value for memory (%s)"),
+			  opt_mem->answer);
+	}
+	segs_mb = mb;
+    }
+
     slic0 = flag_n->answer;
 
     outname = opt_out->answer;
@@ -263,6 +283,33 @@
     G_debug(1, "yerrperstrip = %g", yerrperstrip);
     G_debug(1, "numk = %d", numk);
 
+    /* segment structures */
+    k_mb = 2 * (sizeof(DCELL) * nbands + 2 * sizeof(double)) + sizeof(double);
+    k_mb = k_mb * numk / (1024. * 1024.);
+
+    G_debug(1, "MB for seeds: %g", k_mb);
+    if (k_mb >= segs_mb)
+	G_fatal_error(_("Not enough memory, increase %s option"), opt_mem->answer);
+
+    segs_mb -= k_mb;
+    G_debug(1, "MB for temporary data: %g", segs_mb);
+
+    nseg = 1024. * 1024. * segs_mb / (64 * 64 * (sizeof(DCELL) * nbands + sizeof(double) * 2 + sizeof(int)));
+    G_debug(1, "Number of segments in memory: %d", nseg);
+
+    if (Segment_open(&bands_seg, G_tempfile(), nrows, ncols, 64, 64,
+                     sizeof(DCELL) * nbands, nseg) != 1)
+	G_fatal_error("Unable to create input temporary file");
+
+    if (Segment_open(&k_seg, G_tempfile(), nrows, ncols, 64, 64,
+                     sizeof(int), nseg) != 1)
+	G_fatal_error("Unable to create input temporary file");
+
+    if (Segment_open(&dist_seg, G_tempfile(), nrows, ncols, 64, 64,
+                     sizeof(double) * 2, nseg) != 1)
+	G_fatal_error("Unable to create input temporary file");
+
+
     /* load input bands */
     G_message(_("Loading input..."));
     pdata = G_malloc(sizeof(DCELL *) * nbands);
@@ -282,28 +329,33 @@
 			   &drange);
 	Rast_get_fp_range_min_max(&drange, &min[b], &max[b]);
 	rng[b] = max[b] - min[b];
-
     }
 
-    pdata = G_malloc(sizeof(DCELL **) * nrows);
+    pdata = G_malloc(sizeof(DCELL) * nbands);
+    dists = G_malloc(sizeof(double) * 2);
+    dists[0] = dists[1] = 0;
+    k = -1;
     for (row = 0; row < nrows; row++) {
 	G_percent(row, nrows, 2);
 
-	pdata[row] = G_malloc(sizeof(DCELL *) * ncols);
-
 	for (b = 0; b < nbands; b++)
 	    Rast_get_d_row(ifd[b], ibuf[b], row);
 	for (col = 0; col < ncols; col++) {
-
-	    pdata[row][col] = G_malloc(sizeof(DCELL) * nbands);
-
 	    for (b = 0; b < nbands; b++) {
 		if (Rast_is_d_null_value(&ibuf[b][col])) {
-		    Rast_set_d_null_value(pdata[row][col], nbands);
+		    Rast_set_d_null_value(pdata, nbands);
 		    break;
 		}
-		pdata[row][col][b] = (ibuf[b][col] - min[b]) / rng[b];
+		pdata[b] = (ibuf[b][col] - min[b]) / rng[b];
 	    }
+	    if (Segment_put(&bands_seg, (void *)pdata, row, col) != 1)
+		G_fatal_error(_("Unable to write to temporary file"));
+
+	    if (Segment_put(&k_seg, (void *)&k, row, col) != 1)
+		G_fatal_error(_("Unable to write to temporary file"));
+
+	    if (Segment_put(&dist_seg, (void *)&dists, row, col) != 1)
+		G_fatal_error(_("Unable to write to temporary file"));
 	}
     }
     G_percent(nrows, nrows, 2);
@@ -362,9 +414,10 @@
 
 	    seedy = (y * offset + yoff + ye);
 
-	    if (!Rast_is_d_null_value(pdata[seedy][seedx])) {
+	    Segment_get(&bands_seg, (void *)pdata, seedy, seedx);
+	    if (!Rast_is_d_null_value(pdata)) {
 		for (b = 0; b < nbands; b++) {
-		    kseedsb[k][b] = pdata[seedy][seedx][b];
+		    kseedsb[k][b] = pdata[b];
 		}
 		kseedsx[k] = seedx;
 		kseedsy[k] = seedy;
@@ -375,23 +428,6 @@
     if (k != numk)
 	G_warning(_("Initialized %d of %d seeds"), k, numk);
 
-    /* allocate cell variables */
-    klabels = G_malloc(sizeof(int *) * nrows);
-
-    for (row = 0; row < nrows; row++) {
-	klabels[row] = G_malloc(sizeof(int) * ncols);
-	for (col = 0; col < ncols; col++)
-	    klabels[row][col] = -1;
-    }
-
-    dists = G_malloc(sizeof(double **) * nrows);
-    for (row = 0; row < nrows; row++) {
-	dists[row] = G_malloc(sizeof(double *) * ncols);
-	for (col = 0; col < ncols; col++) {
-	    dists[row][col] = G_malloc(sizeof(double) * 2);
-	}
-    }
-
     maxdistspec = maxdistspecprev = 0;
 
     /* magic factor */
@@ -403,10 +439,11 @@
 
 	schange = 0;
 
+	dists[0] = 0;
+	dists[1] = 1E+9;
 	for (row = 0; row < nrows; row++) {
 	    for (col = 0; col < ncols; col++) {
-		dists[row][col][0] = 0;
-		dists[row][col][1] = 1E+9;
+		Segment_put(&dist_seg, (void *)&dists, row, col);
 	    }
 	}
 
@@ -420,13 +457,15 @@
 		dy = y - kseedsy[k];
 		
 		for (x = x1; x <= x2; x++) {
-		    if (Rast_is_d_null_value(pdata[y][x]))
+		    Segment_get(&bands_seg, (void *)pdata, y, x);
+		    if (Rast_is_d_null_value(pdata))
 			continue;
-		    
+
+		    Segment_get(&dist_seg, (void *)dists, y, x);
 		    dist = 0.0;
 		    for (b = 0; b < nbands; b++) {
-			dist += (pdata[y][x][b] - kseedsb[k][b]) *
-			        (pdata[y][x][b] - kseedsb[k][b]);
+			dist += (pdata[b] - kseedsb[k][b]) *
+			        (pdata[b] - kseedsb[k][b]);
 		    }
 		    dist /= nbands;
 
@@ -437,10 +476,12 @@
 		    distsum = dist / maxdistspeck[k] + distxy * invwt;
 		    /* dist = sqrt(dist) + sqrt(distxy*invwt);  this is more exact */
 		    /*------------------------------------------------------------------------ */
-		    if (distsum < dists[y][x][1]) {
-			dists[y][x][0] = dist;
-			dists[y][x][1] = distsum;
-			klabels[y][x] = k;
+		    if (distsum < dists[1]) {
+			dists[0] = dist;
+			dists[1] = distsum;
+
+			Segment_put(&dist_seg, (void *)dists, y, x);
+			Segment_put(&k_seg, (void *)&k, y, x);
 		    }
 
 		}		/* for( x=x1 */
@@ -455,10 +496,11 @@
 	    }
 	    for (row = 0; row < nrows; row++) {
 		for (col = 0; col < ncols; col++) {
-		    k = klabels[row][col];
+		    Segment_get(&k_seg, (void *)&k, row, col);
 		    if (k >= 0) {
-			if (maxdistspeck[k] < dists[row][col][0])
-			    maxdistspeck[k] = dists[row][col][0];
+			Segment_get(&dist_seg, (void *)dists, row, col);
+			if (maxdistspeck[k] < dists[0])
+			    maxdistspeck[k] = dists[0];
 		    }
 		}
 	    }
@@ -468,10 +510,11 @@
 	    maxdistspec = 0;
 	    for (row = 0; row < nrows; row++) {
 		for (col = 0; col < ncols; col++) {
-		    k = klabels[row][col];
+		    Segment_get(&k_seg, (void *)&k, row, col);
 		    if (k >= 0) {
-			if (maxdistspec < dists[row][col][0])
-			    maxdistspec = dists[row][col][0];
+			Segment_get(&dist_seg, (void *)dists, row, col);
+			if (maxdistspec < dists[0])
+			    maxdistspec = dists[0];
 		    }
 		}
 	    }
@@ -490,13 +533,15 @@
 
 	for (row = 0; row < nrows; row++) {
 	    for (col = 0; col < ncols; col++) {
-		if (klabels[row][col] >= 0) {
+		Segment_get(&k_seg, (void *)&k, row, col);
+		if (k >= 0) {
+		    Segment_get(&bands_seg, (void *)pdata, row, col);
 		    for (b = 0; b < nbands; b++) {
-			sigmab[klabels[row][col]][b] += pdata[row][col][b];
+			sigmab[k][b] += pdata[b];
 		    }
-		    sigmax[klabels[row][col]] += col;
-		    sigmay[klabels[row][col]] += row;
-		    clustersize[klabels[row][col]] += 1;
+		    sigmax[k] += col;
+		    sigmay[k] += row;
+		    clustersize[k] += 1;
 		}
 	    }
 	}
@@ -545,12 +590,6 @@
 	G_message(_("SLIC converged after %d iterations"), itr);
 
     /* free */
-    for (row = 0; row < nrows; row++) {
-	for (col = 0; col < ncols; col++)
-	    G_free(dists[row][col]);
-	G_free(dists[row]);
-    }
-    G_free(dists);
 
     for (k = 0; k < numk; k++) {
 	G_free(kseedsb[k]);
@@ -564,40 +603,49 @@
     G_free(sigmay);
     G_free(clustersize);
 
-    nlabels = G_malloc(sizeof(int *) * nrows);
-    for (row = 0; row < nrows; row++) {
-	nlabels[row] = G_malloc(sizeof(int) * ncols);
-	memset(nlabels[row], 0, sizeof(int) * ncols);
-    }
+    Segment_close(&dist_seg);
 
-    numlabels = SLIC_EnforceLabelConnectivity(klabels, ncols, nrows, 
-                                              nlabels, 0);
+    if (Segment_open(&nk_seg, G_tempfile(), nrows, ncols, 64, 64,
+                     sizeof(int), nseg) != 1)
+	G_fatal_error("Unable to create input temporary file");
+
+    numlabels = SLIC_EnforceLabelConnectivity(&k_seg, ncols, nrows, 
+                                              &nk_seg, 0);
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++) {
-	    if (klabels[row][col] >= 0)
-		klabels[row][col] = nlabels[row][col];
+	    Segment_get(&k_seg, (void *)&k, row, col);
+	    if (k >= 0) {
+		int n;
+
+		Segment_get(&nk_seg, (void *)&n, row, col);
+		Segment_put(&k_seg, (void *)&n, row, col);
+	    }
 	}
     }
-    
-    G_free(nlabels);
 
+    Segment_close(&nk_seg);
+
     if (minsize > 1)
-	numlabels = merge_small_clumps(pdata, nbands, klabels,
+	numlabels = merge_small_clumps(&bands_seg, nbands, &k_seg,
 	                               numlabels, 0, minsize);
 
+    Segment_close(&bands_seg);
+
     outfd = Rast_open_new(outname, CELL_TYPE);
     obuf = Rast_allocate_c_buf();
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++) {
-	    if (klabels[row][col] < 0)
+	    Segment_get(&k_seg, (void *)&k, row, col);
+	    if (k < 0)
 		Rast_set_c_null_value(&obuf[col], 1);
 	    else
-		obuf[col] = klabels[row][col] + 1;	/* +1 to avoid category value 0 */
+		obuf[col] = k + 1;	/* +1 to avoid category value 0 */
 	}
 	Rast_put_row(outfd, obuf, CELL_TYPE);
     }
 
     Rast_close(outfd);
+    Segment_close(&k_seg);
 
     /* history */
     Rast_short_history(outname, "raster", &hist);
@@ -613,22 +661,23 @@
 }
 
 
-int SLIC_EnforceLabelConnectivity(int **labels, int ncols, int nrows,
-                                  int **nlabels,	/*new labels */
+int SLIC_EnforceLabelConnectivity(SEGMENT *k_seg, int ncols, int nrows,
+                                  SEGMENT *nk_seg,	/*new labels */
 				  int minsize)
 {
 
     const int dx4[4] = { -1, 0, 1, 0 };
     const int dy4[4] = { 0, -1, 0, 1 };
 
-    int n, label, adjlabel;
+    int n, label, adjlabel, k, k2, nk;
     int row, col;
     int x, y, c, count;
     int *xvec, *yvec, vec_alloc;
 
+    nk = -1;
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++)
-	    nlabels[row][col] = -1;
+	    Segment_put(nk_seg, (void *)&nk, row, col);
     }
     label = 0;
 
@@ -640,8 +689,10 @@
 
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++) {
-	    if (labels[row][col] >= 0 && nlabels[row][col] < 0) {
-		nlabels[row][col] = label;
+	    Segment_get(k_seg, (void *)&k, row, col);
+	    Segment_get(nk_seg, (void *)&nk, row, col);
+	    if (k >= 0 && nk < 0) {
+		Segment_put(nk_seg, (void *)&label, row, col);
 
 		/*--------------------
 		 Start a new segment
@@ -657,8 +708,9 @@
 		    x = xvec[0] + dx4[n];
 		    y = yvec[0] + dy4[n];
 		    if ((x >= 0 && x < ncols) && (y >= 0 && y < nrows)) {
-			if (nlabels[y][x] >= 0)
-			    adjlabel = nlabels[y][x];
+			Segment_get(nk_seg, (void *)&nk, y, x);
+			if (nk >= 0)
+			    adjlabel = nk;
 		    }
 		}
 
@@ -670,8 +722,9 @@
 
 			if ((x >= 0 && x < ncols) && (y >= 0 && y < nrows)) {
 
-			    if (0 > nlabels[y][x] &&
-				labels[row][col] == labels[y][x]) {
+			    Segment_get(k_seg, (void *)&k2, y, x);
+			    Segment_get(nk_seg, (void *)&nk, y, x);
+			    if (0 > nk && k == k2) {
 				if (vec_alloc <= count) {
 				    vec_alloc += 100;
 				    xvec =
@@ -683,7 +736,7 @@
 				}
 				xvec[count] = x;
 				yvec[count] = y;
-				nlabels[y][x] = label;
+				Segment_put(nk_seg, (void *)&label, y, x);
 				count++;
 			    }
 			}
@@ -696,7 +749,7 @@
 		-------------------------------------------------------*/
 		if (count < minsize) {
 		    for (c = 0; c < count; c++) {
-			nlabels[yvec[c]][xvec[c]] = adjlabel;
+			Segment_put(nk_seg, (void *)&adjlabel, yvec[c], xvec[c]);
 		    }
 		    label--;
 		}

Modified: grass-addons/grass7/imagery/i.superpixels.slic/minsize.c
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/minsize.c	2017-01-30 20:34:57 UTC (rev 70459)
+++ grass-addons/grass7/imagery/i.superpixels.slic/minsize.c	2017-01-30 22:13:45 UTC (rev 70460)
@@ -1,5 +1,6 @@
 #include <grass/gis.h>
 #include <grass/raster.h>
+#include <grass/segment.h>	
 #include <grass/glocale.h>
 #include "pavl.h"
 #include "rclist.h"
@@ -138,18 +139,20 @@
 static int (*get_neighbors)(int row, int col, int nrows, int ncols,
 			       int neighbors[8][2]);
 
-static int update_cid(int **klabels, int row, int col, int old_id, int new_id)
+static int update_cid(SEGMENT *k_seg, int row, int col, int old_id, int new_id)
 {
     int nrows, ncols, rown, coln, n;
+    int this_id;
     int neighbors[8][2];
     struct rc next;
     struct rclist rilist;
 
-    if (klabels[row][col] != old_id) {
+    Segment_get(k_seg, (void *)&this_id, row, col);
+    if (this_id != old_id) {
 	G_fatal_error(_("Wrong id %d for row %d, col %d"), 
-	              klabels[row][col], row, col);
+	              this_id, row, col);
     }
-    klabels[row][col] = new_id;
+    Segment_put(k_seg, (void *)&new_id, row, col);
 
     nrows = Rast_window_rows();
     ncols = Rast_window_cols();
@@ -166,8 +169,9 @@
 	    rown = neighbors[n][0];
 	    coln = neighbors[n][1];
 
-	    if (klabels[rown][coln] == old_id) {
-		klabels[rown][coln] = new_id;
+	    Segment_get(k_seg, (void *)&this_id, rown, coln);
+	    if (this_id == old_id) {
+		Segment_put(k_seg, (void *)&new_id, rown, coln);
 		rclist_add(&rilist, rown, coln);
 	    }
 
@@ -180,7 +184,7 @@
 }
 
 static int find_best_neighbour(DCELL **clumpbsum, int nbands, int *clumpsize,
-                               int **klabels, int row, int col,
+                               SEGMENT *k_seg, int row, int col,
 			       int this_id, int *best_id)
 {
     int rown, coln, n, count, b;
@@ -222,7 +226,9 @@
 	    rown = neighbors[n][0];
 	    coln = neighbors[n][1];
 
-	    if (klabels[rown][coln] < 0)
+	    /* get neighbor ID */
+	    Segment_get(k_seg, (void *)&ngbr_id, rown, coln);
+	    if (ngbr_id < 0)
 		continue;
 
 	    ngbr_rc.row = rown;
@@ -236,8 +242,6 @@
 	    if (pavl_insert(visited, pngbr_rc) == NULL) {
 		pngbr_rc = NULL;
 
-		/* get neighbor ID */
-		ngbr_id = klabels[rown][coln];
 		/* same neighbour */
 		if (ngbr_id == this_id) {
 		    count++;
@@ -285,8 +289,8 @@
     return (*best_id >= 0);
 }
 
-int merge_small_clumps(DCELL ***pdata, int nbands,
-                       int **klabels, int nlabels,
+int merge_small_clumps(SEGMENT *bands_seg, int nbands,
+                       SEGMENT *k_seg, int nlabels,
                        int diag, int minsize)
 {
     int row, col, nrows, ncols, i, b;
@@ -295,6 +299,7 @@
     int reg_size;
     int *clumpsize, n_clumps_new;
     DCELL **clumpbsum;
+    DCELL *pdata;
 
     /* merge with best (most similar) neighbour */
 
@@ -324,17 +329,19 @@
 	for (b = 0; b < nbands; b++)
 	    clumpbsum[i][b] = 0;
     }
+    pdata = G_malloc(sizeof(DCELL) * nbands);
 
     G_message(_("Merging clumps smaller than %d cells..."), minsize);
 
     /* get clump sizes and band sums */
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++) {
-	    this_id = klabels[row][col];
+	    Segment_get(k_seg, (void *)&this_id, row, col);
 	    if (this_id >= 0) {
 		clumpsize[this_id]++;
+		Segment_get(bands_seg, (void *)pdata, row, col);
 		for (b = 0; b < nbands; b++)
-		    clumpbsum[this_id][b] += pdata[row][col][b];
+		    clumpbsum[this_id][b] += pdata[b];
 	    }
 	}
     }
@@ -347,7 +354,7 @@
 	for (col = 0; col < ncols; col++) {
 
 	    /* get clump id */
-	    this_id = klabels[row][col];
+	    Segment_get(k_seg, (void *)&this_id, row, col);
 	    if (this_id < 0)
 		continue;
 
@@ -357,12 +364,12 @@
 	    while (reg_size < minsize && best_id >= 0) {
 		best_id = -1;
 
-		find_best_neighbour(clumpbsum, nbands, clumpsize, klabels,
+		find_best_neighbour(clumpbsum, nbands, clumpsize, k_seg,
 				    row, col, this_id, &best_id);
 
 		if (best_id >= 0) {
 		    /* update cid */
-		    update_cid(klabels, row, col, this_id, best_id);
+		    update_cid(k_seg, row, col, this_id, best_id);
 		    /* mark as merged */
 		    for (b = 0; b < nbands; b++)
 			clumpbsum[best_id][b] += clumpbsum[this_id][b];
@@ -391,9 +398,11 @@
 
 	for (col = 0; col < ncols; col++) {
 
-	    this_id = klabels[row][col];
-	    if (this_id >= 0)
-		klabels[row][col] = clumpsize[this_id];
+	    Segment_get(k_seg, (void *)&this_id, row, col);
+	    if (this_id >= 0) {
+		this_id = clumpsize[this_id];
+		Segment_put(k_seg, (void *)&this_id, row, col);
+	    }
 	}
     }
     G_percent(1, 1, 1);



More information about the grass-commit mailing list