[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