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

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Feb 2 12:44:02 PST 2017


Author: mmetz
Date: 2017-02-02 12:44:02 -0800 (Thu, 02 Feb 2017)
New Revision: 70478

Added:
   grass-addons/grass7/imagery/i.superpixels.slic/cache.c
   grass-addons/grass7/imagery/i.superpixels.slic/cache.h
Modified:
   grass-addons/grass7/imagery/i.superpixels.slic/main.c
   grass-addons/grass7/imagery/i.superpixels.slic/minsize.c
Log:
i.superpixels.slic: +generic cache for RAM and SEG mode

Added: grass-addons/grass7/imagery/i.superpixels.slic/cache.c
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/cache.c	                        (rev 0)
+++ grass-addons/grass7/imagery/i.superpixels.slic/cache.c	2017-02-02 20:44:02 UTC (rev 70478)
@@ -0,0 +1,93 @@
+#include <string.h>
+#include <grass/raster.h>
+#include <grass/segment.h>
+#include <grass/glocale.h>
+#include "cache.h"
+
+static void *cache_get_r(struct cache *c, void *p, int row, int col)
+{
+    return memcpy(p, c->r[row][col], c->n);
+}
+
+static void *cache_put_r(struct cache *c, void *p, int row, int col)
+{
+    return memcpy(c->r[row][col], p, c->n);
+}
+
+static void *cache_get_s(struct cache *c, void *p, int row, int col)
+{
+    Segment_get(&c->s, p, row, col);
+
+    return  p;
+}
+
+static void *cache_put_s(struct cache *c, void *p, int row, int col)
+{
+    if (Segment_put(&c->s, p, row, col) != 1)
+	G_fatal_error(_("Unable to write to temporary file"));
+
+    return p;
+}
+
+int cache_create(struct cache *c, int nrows, int ncols, int seg_size,
+                 int use_seg, int nbytes, int nseg)
+{
+    c->n = nbytes;
+    c->rows = nrows;
+    c->cols = ncols;
+
+    if (use_seg) {
+	if (Segment_open(&c->s, G_tempfile(), nrows, ncols, seg_size, seg_size,
+			 nbytes, nseg) != 1)
+	    G_fatal_error("Unable to create temporary file");
+
+	c->r = NULL;
+	c->get = cache_get_s;
+	c->put = cache_put_s;
+    }
+    else {
+	int row, col;
+
+	c->r = G_malloc(sizeof(char **) * c->rows);
+	for (row = 0; row < c->rows; row++) {
+	    c->r[row] = G_malloc(sizeof(char *) * c->cols);
+	    c->r[row][0] = G_malloc(sizeof(char) * c->cols * c->n);
+	    for (col = 1; col < c->cols; col++) {
+		c->r[row][col] = c->r[row][col - 1] + c->n;
+	    }
+	}
+
+	c->get = cache_get_r;
+	c->put = cache_put_r;
+    }
+
+    return 1;
+}
+
+int cache_destroy(struct cache *c)
+{
+    if (c->r == NULL) {
+	Segment_close(&c->s);
+    }
+    else {
+	int row;
+
+	for (row = 0; row < c->rows; row++) {
+	    G_free(c->r[row][0]);
+	    G_free(c->r[row]);
+	}
+	G_free(c->r);
+    }
+
+    return 1;
+}
+
+void *cache_get(struct cache *c, void *p, int row, int col)
+{
+    return c->get(c, p, row, col);
+}
+
+void *cache_put(struct cache *c, void *p, int row, int col)
+{
+    return c->put(c, p, row, col);
+}


Property changes on: grass-addons/grass7/imagery/i.superpixels.slic/cache.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native

Added: grass-addons/grass7/imagery/i.superpixels.slic/cache.h
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/cache.h	                        (rev 0)
+++ grass-addons/grass7/imagery/i.superpixels.slic/cache.h	2017-02-02 20:44:02 UTC (rev 70478)
@@ -0,0 +1,17 @@
+/* grid cache */
+
+struct cache
+{
+    SEGMENT s;
+    char ***r;
+    int n;		/* data size per cell in bytes */
+    int rows, cols;
+    void *(* get)(struct cache *c, void *p, int row, int col);
+    void *(* put)(struct cache *c, void *p, int row, int col);
+};
+
+int cache_create(struct cache *c, int nrows, int ncols, int seg_size,
+                 int use_seg, int nbytes, int nseg);
+int cache_destroy(struct cache *c);
+void *cache_get(struct cache *c, void *p, int row, int col);
+void *cache_put(struct cache *c, void *p, int row, int col);


Property changes on: grass-addons/grass7/imagery/i.superpixels.slic/cache.h
___________________________________________________________________
Added: svn:mime-type
   + text/x-chdr
Added: svn:eol-style
   + native

Modified: grass-addons/grass7/imagery/i.superpixels.slic/main.c
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/main.c	2017-02-02 16:59:40 UTC (rev 70477)
+++ grass-addons/grass7/imagery/i.superpixels.slic/main.c	2017-02-02 20:44:02 UTC (rev 70478)
@@ -25,6 +25,7 @@
 #include <grass/segment.h>	
 #include <grass/imagery.h>
 #include <grass/glocale.h>
+#include "cache.h"
 
 #ifndef MAX
 #define MAX(x,y) ((x) > (y) ? (x) : (y))
@@ -33,11 +34,11 @@
 #define MIN(x,y) ((x) < (y) ? (x) : (y))
 #endif
 
-int SLIC_EnforceLabelConnectivity(SEGMENT *k_seg, int ncols, int nrows,
-				  SEGMENT *nk_seg, int minsize);
+int SLIC_EnforceLabelConnectivity(struct cache *k_seg, int ncols, int nrows,
+				  struct cache *nk_seg, int minsize);
 
-int merge_small_clumps(SEGMENT *bands_seg, int nbands,
-                       SEGMENT *k_seg, int nlabels,
+int merge_small_clumps(struct cache *bands_seg, int nbands,
+                       struct cache *k_seg, int nlabels,
                        int diag, int minsize);
 
 int main(int argc, char *argv[])
@@ -60,8 +61,8 @@
     struct Colors colors;
     struct History hist;
     
-    int nseg;
-    double segs_mb, k_mb;
+    int seg_size, nseg, nsegc, nseg_total, use_seg;
+    double segs_mb, k_mb, all_mb;
 
     int n_iterations, n_super_pixels, numk, numlabels, slic0;
     int nrows, ncols, row, col, b, k;
@@ -72,7 +73,7 @@
     int offset;
     DCELL *pdata;
     double *dists;
-    SEGMENT bands_seg, k_seg, nk_seg, dist_seg;
+    struct cache bands_seg, k_seg, nk_seg, dist_seg;
     int schange;
 
     double xerrperstrip, yerrperstrip;
@@ -284,35 +285,65 @@
     G_debug(1, "numk = %d", numk);
 
     /* segment structures */
-    k_mb = 2 * (sizeof(DCELL) * nbands + 2 * sizeof(double)) + sizeof(double);
+    k_mb = 2 * (sizeof(DCELL *) * 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 - 10)
 	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);
+    
+    all_mb = 3 * (sizeof(char **) * ((double) nrows / (1024. * 1024.)) +
+             sizeof(char *) * ((double) nrows / 1024.) * ((double) ncols / 1024.)) +
+             (sizeof(DCELL) * nbands + sizeof(double) * 2 + sizeof(int)) * 
+	     ((double) nrows / 1024.) * ((double) ncols / 1024.);
 
-    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);
+    G_debug(1, "MB for all in RAM: %g", all_mb);
 
-    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");
+    use_seg = 0;
+    /* TODO: k_mb + all_mb is smaller than the actual memory consumption
+     * when using all-in-ram mode */
+    if (segs_mb < k_mb + all_mb)
+	use_seg = 1;
 
-    if (Segment_open(&k_seg, G_tempfile(), nrows, ncols, 64, 64,
-                     sizeof(int), nseg) != 1)
-	G_fatal_error("Unable to create input temporary file");
+    segs_mb -= k_mb;
 
-    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");
+    seg_size = 64;
+    nseg = 1024. * 1024. * segs_mb /
+           (seg_size * seg_size * (sizeof(DCELL) * nbands +
+	    sizeof(double) * 2 + sizeof(int)));
 
+    nsegc = ncols / seg_size;
+    if (ncols % seg_size)
+	nsegc++;
+    nseg_total = nsegc * ((nrows + seg_size - 1) / seg_size);
 
+    if (!use_seg) {
+	G_message(_("Cache data in memory mode"));
+    }
+    else {
+	G_message(_("Cache data on disk mode"));
+	if (nseg > nseg_total)
+	    nseg = nseg_total;
+	G_verbose_message(_("Number of segments in memory: %d of %d"), nseg, nseg_total);
+
+    }
+
+    if (cache_create(&bands_seg, nrows, ncols, seg_size, use_seg,
+		     sizeof(DCELL) * nbands, nseg) != 1)
+	G_fatal_error("Unable to create grid cache");
+
+    if (cache_create(&dist_seg, nrows, ncols, seg_size, use_seg,
+		     sizeof(double) * 2, nseg) != 1)
+	G_fatal_error("Unable to create grid cache");
+
+    if (cache_create(&k_seg, nrows, ncols, seg_size, use_seg,
+		     sizeof(int), nseg) != 1)
+	G_fatal_error("Unable to create grid cache");
+
     /* load input bands */
     G_message(_("Loading input..."));
-    pdata = G_malloc(sizeof(DCELL *) * nbands);
 
     ifd = G_malloc(sizeof(int *) * nbands);
     ibuf = G_malloc(sizeof(DCELL **) * nbands);
@@ -348,14 +379,9 @@
 		}
 		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"));
+	    cache_put(&bands_seg, pdata, row, col);
+	    cache_put(&k_seg, &k, row, col);
+	    cache_put(&dist_seg, dists, row, col);
 	}
     }
     G_percent(nrows, nrows, 2);
@@ -414,7 +440,7 @@
 
 	    seedy = (y * offset + yoff + ye);
 
-	    Segment_get(&bands_seg, (void *)pdata, seedy, seedx);
+	    cache_get(&bands_seg, pdata, seedy, seedx);
 	    if (!Rast_is_d_null_value(pdata)) {
 		for (b = 0; b < nbands; b++) {
 		    kseedsb[k][b] = pdata[b];
@@ -444,7 +470,7 @@
 	dists[1] = 1E+9;
 	for (row = 0; row < nrows; row++) {
 	    for (col = 0; col < ncols; col++) {
-		Segment_put(&dist_seg, (void *)&dists, row, col);
+		cache_put(&dist_seg, dists, row, col);
 	    }
 	}
 
@@ -458,11 +484,11 @@
 		dy = y - kseedsy[k];
 		
 		for (x = x1; x <= x2; x++) {
-		    Segment_get(&bands_seg, (void *)pdata, y, x);
+		    cache_get(&bands_seg, pdata, y, x);
 		    if (Rast_is_d_null_value(pdata))
 			continue;
 
-		    Segment_get(&dist_seg, (void *)dists, y, x);
+		    cache_get(&dist_seg, dists, y, x);
 		    dist = 0.0;
 		    for (b = 0; b < nbands; b++) {
 			dist += (pdata[b] - kseedsb[k][b]) *
@@ -481,8 +507,8 @@
 			dists[0] = dist;
 			dists[1] = distsum;
 
-			Segment_put(&dist_seg, (void *)dists, y, x);
-			Segment_put(&k_seg, (void *)&k, y, x);
+			cache_put(&dist_seg, dists, y, x);
+			cache_put(&k_seg, &k, y, x);
 		    }
 
 		}		/* for( x=x1 */
@@ -497,9 +523,9 @@
 	    }
 	    for (row = 0; row < nrows; row++) {
 		for (col = 0; col < ncols; col++) {
-		    Segment_get(&k_seg, (void *)&k, row, col);
+		    cache_get(&k_seg, &k, row, col);
 		    if (k >= 0) {
-			Segment_get(&dist_seg, (void *)dists, row, col);
+			cache_get(&dist_seg, dists, row, col);
 			if (maxdistspeck[k] < dists[0])
 			    maxdistspeck[k] = dists[0];
 		    }
@@ -511,9 +537,9 @@
 	    maxdistspec = 0;
 	    for (row = 0; row < nrows; row++) {
 		for (col = 0; col < ncols; col++) {
-		    Segment_get(&k_seg, (void *)&k, row, col);
+		    cache_get(&k_seg, &k, row, col);
 		    if (k >= 0) {
-			Segment_get(&dist_seg, (void *)dists, row, col);
+			cache_get(&dist_seg, dists, row, col);
 			if (maxdistspec < dists[0])
 			    maxdistspec = dists[0];
 		    }
@@ -534,9 +560,9 @@
 
 	for (row = 0; row < nrows; row++) {
 	    for (col = 0; col < ncols; col++) {
-		Segment_get(&k_seg, (void *)&k, row, col);
+		cache_get(&k_seg, &k, row, col);
 		if (k >= 0) {
-		    Segment_get(&bands_seg, (void *)pdata, row, col);
+		    cache_get(&bands_seg, pdata, row, col);
 		    for (b = 0; b < nbands; b++) {
 			sigmab[k][b] += pdata[b];
 		    }
@@ -607,39 +633,37 @@
     G_free(sigmay);
     G_free(clustersize);
 
-    Segment_close(&dist_seg);
+    cache_destroy(&dist_seg);
+    cache_create(&nk_seg, nrows, ncols, seg_size, use_seg,
+		 sizeof(int), nseg);
 
-    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++) {
-	    Segment_get(&k_seg, (void *)&k, row, col);
+	    cache_get(&k_seg, &k, row, col);
 	    if (k >= 0) {
 		int n;
 
-		Segment_get(&nk_seg, (void *)&n, row, col);
-		Segment_put(&k_seg, (void *)&n, row, col);
+		cache_get(&nk_seg, &n, row, col);
+		cache_put(&k_seg, &n, row, col);
 	    }
 	}
     }
 
-    Segment_close(&nk_seg);
+    cache_destroy(&nk_seg);
 
     if (minsize > 1)
 	numlabels = merge_small_clumps(&bands_seg, nbands, &k_seg,
 	                               numlabels, 0, minsize);
 
-    Segment_close(&bands_seg);
+    cache_destroy(&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++) {
-	    Segment_get(&k_seg, (void *)&k, row, col);
+	    cache_get(&k_seg, &k, row, col);
 	    if (k < 0)
 		Rast_set_c_null_value(&obuf[col], 1);
 	    else
@@ -649,7 +673,7 @@
     }
 
     Rast_close(outfd);
-    Segment_close(&k_seg);
+    cache_destroy(&k_seg);
 
     /* history */
     Rast_short_history(outname, "raster", &hist);
@@ -667,8 +691,8 @@
 }
 
 
-int SLIC_EnforceLabelConnectivity(SEGMENT *k_seg, int ncols, int nrows,
-                                  SEGMENT *nk_seg,	/*new labels */
+int SLIC_EnforceLabelConnectivity(struct cache *k_seg, int ncols, int nrows,
+                                  struct cache *nk_seg,	/*new labels */
 				  int minsize)
 {
 
@@ -683,7 +707,7 @@
     nk = -1;
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++)
-	    Segment_put(nk_seg, (void *)&nk, row, col);
+	    cache_put(nk_seg, &nk, row, col);
     }
     label = 0;
 
@@ -695,10 +719,10 @@
 
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++) {
-	    Segment_get(k_seg, (void *)&k, row, col);
-	    Segment_get(nk_seg, (void *)&nk, row, col);
+	    cache_get(k_seg, &k, row, col);
+	    cache_get(nk_seg, &nk, row, col);
 	    if (k >= 0 && nk < 0) {
-		Segment_put(nk_seg, (void *)&label, row, col);
+		cache_put(nk_seg, &label, row, col);
 
 		/*--------------------
 		 Start a new segment
@@ -714,7 +738,7 @@
 		    x = xvec[0] + dx4[n];
 		    y = yvec[0] + dy4[n];
 		    if ((x >= 0 && x < ncols) && (y >= 0 && y < nrows)) {
-			Segment_get(nk_seg, (void *)&nk, y, x);
+			cache_get(nk_seg, &nk, y, x);
 			if (nk >= 0)
 			    adjlabel = nk;
 		    }
@@ -728,8 +752,8 @@
 
 			if ((x >= 0 && x < ncols) && (y >= 0 && y < nrows)) {
 
-			    Segment_get(k_seg, (void *)&k2, y, x);
-			    Segment_get(nk_seg, (void *)&nk, y, x);
+			    cache_get(k_seg, &k2, y, x);
+			    cache_get(nk_seg, &nk, y, x);
 			    if (0 > nk && k == k2) {
 				if (vec_alloc <= count) {
 				    vec_alloc += 100;
@@ -742,7 +766,7 @@
 				}
 				xvec[count] = x;
 				yvec[count] = y;
-				Segment_put(nk_seg, (void *)&label, y, x);
+				cache_put(nk_seg, &label, y, x);
 				count++;
 			    }
 			}
@@ -755,7 +779,7 @@
 		-------------------------------------------------------*/
 		if (count < minsize) {
 		    for (c = 0; c < count; c++) {
-			Segment_put(nk_seg, (void *)&adjlabel, yvec[c], xvec[c]);
+			cache_put(nk_seg, &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-02-02 16:59:40 UTC (rev 70477)
+++ grass-addons/grass7/imagery/i.superpixels.slic/minsize.c	2017-02-02 20:44:02 UTC (rev 70478)
@@ -1,9 +1,10 @@
 #include <grass/gis.h>
 #include <grass/raster.h>
-#include <grass/segment.h>	
+#include <grass/segment.h>
 #include <grass/glocale.h>
 #include "pavl.h"
 #include "rclist.h"
+#include "cache.h"
 
 struct nbr_cnt {
     int id;
@@ -139,7 +140,7 @@
 static int (*get_neighbors)(int row, int col, int nrows, int ncols,
 			       int neighbors[8][2]);
 
-static int update_cid(SEGMENT *k_seg, int row, int col, int old_id, int new_id)
+static int update_cid(struct cache *k_seg, int row, int col, int old_id, int new_id)
 {
     int nrows, ncols, rown, coln, n;
     int this_id;
@@ -147,12 +148,12 @@
     struct rc next;
     struct rclist rilist;
 
-    Segment_get(k_seg, (void *)&this_id, row, col);
+    cache_get(k_seg, &this_id, row, col);
     if (this_id != old_id) {
 	G_fatal_error(_("Wrong id %d for row %d, col %d"), 
 	              this_id, row, col);
     }
-    Segment_put(k_seg, (void *)&new_id, row, col);
+    cache_put(k_seg, &new_id, row, col);
 
     nrows = Rast_window_rows();
     ncols = Rast_window_cols();
@@ -169,9 +170,9 @@
 	    rown = neighbors[n][0];
 	    coln = neighbors[n][1];
 
-	    Segment_get(k_seg, (void *)&this_id, rown, coln);
+	    cache_get(k_seg, &this_id, rown, coln);
 	    if (this_id == old_id) {
-		Segment_put(k_seg, (void *)&new_id, rown, coln);
+		cache_put(k_seg, &new_id, rown, coln);
 		rclist_add(&rilist, rown, coln);
 	    }
 
@@ -184,7 +185,7 @@
 }
 
 static int find_best_neighbour(DCELL **clumpbsum, int nbands, int *clumpsize,
-                               SEGMENT *k_seg, int row, int col,
+                               struct cache *k_seg, int row, int col,
 			       int this_id, int *best_id)
 {
     int rown, coln, n, count, b;
@@ -227,7 +228,7 @@
 	    coln = neighbors[n][1];
 
 	    /* get neighbor ID */
-	    Segment_get(k_seg, (void *)&ngbr_id, rown, coln);
+	    cache_get(k_seg, &ngbr_id, rown, coln);
 	    if (ngbr_id < 0)
 		continue;
 
@@ -289,8 +290,8 @@
     return (*best_id >= 0);
 }
 
-int merge_small_clumps(SEGMENT *bands_seg, int nbands,
-                       SEGMENT *k_seg, int nlabels,
+int merge_small_clumps(struct cache *bands_seg, int nbands,
+                       struct cache *k_seg, int nlabels,
                        int diag, int minsize)
 {
     int row, col, nrows, ncols, i, b;
@@ -336,10 +337,10 @@
     /* get clump sizes and band sums */
     for (row = 0; row < nrows; row++) {
 	for (col = 0; col < ncols; col++) {
-	    Segment_get(k_seg, (void *)&this_id, row, col);
+	    cache_get(k_seg, &this_id, row, col);
 	    if (this_id >= 0) {
 		clumpsize[this_id]++;
-		Segment_get(bands_seg, (void *)pdata, row, col);
+		cache_get(bands_seg, pdata, row, col);
 		for (b = 0; b < nbands; b++)
 		    clumpbsum[this_id][b] += pdata[b];
 	    }
@@ -354,7 +355,7 @@
 	for (col = 0; col < ncols; col++) {
 
 	    /* get clump id */
-	    Segment_get(k_seg, (void *)&this_id, row, col);
+	    cache_get(k_seg, &this_id, row, col);
 	    if (this_id < 0)
 		continue;
 
@@ -398,10 +399,10 @@
 
 	for (col = 0; col < ncols; col++) {
 
-	    Segment_get(k_seg, (void *)&this_id, row, col);
+	    cache_get(k_seg, &this_id, row, col);
 	    if (this_id >= 0) {
 		this_id = clumpsize[this_id];
-		Segment_put(k_seg, (void *)&this_id, row, col);
+		cache_put(k_seg, &this_id, row, col);
 	    }
 	}
     }



More information about the grass-commit mailing list