[GRASS-SVN] r70486 - grass-addons/grass7/imagery/i.superpixels.slic
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Feb 4 12:57:58 PST 2017
Author: mmetz
Date: 2017-02-04 12:57:58 -0800 (Sat, 04 Feb 2017)
New Revision: 70486
Modified:
grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html
grass-addons/grass7/imagery/i.superpixels.slic/main.c
Log:
i.superpixels.slic: +perturb option
Modified: grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html 2017-02-04 17:24:56 UTC (rev 70485)
+++ grass-addons/grass7/imagery/i.superpixels.slic/i.superpixels.slic.html 2017-02-04 20:57:58 UTC (rev 70486)
@@ -63,11 +63,28 @@
heterogeneous. This effect becomes stronger with larger differences in
the spectral homogeneity of neighboring superpixels.
+<h4>Perturbing initial superpixel centers</h4>
+Initial superpixel centers can be optimized with the <b>perturb</b>
+option. The objective of this optimization of initial superpixel
+centers is to create more distinct and more homogeneous superpixels.
+Superpixel centers are shifted to more uniform areas, the
+pixel with the smallest gradient. The module guarantees that no two
+superpixel centers are shifted to the same position. The <b>perturb</b>
+option is interpreted as percent of the maximum allowable shift
+distance such that no two superpixel centers can obtain the same
+position.
+
<h2>REFERENCES</h2>
-"SLIC Superpixels", Radhakrishna Achanta, Appu Shaji, Kevin Smith,
+SLIC Superpixels. 2010. Radhakrishna Achanta, Appu Shaji, Kevin Smith,
Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk. EPFL Technical
-Report no. 149300, June 2010.
+Report no. 149300. <br>
+SLIC Superpixels Compared to State-of-the-art Superpixel Methods. 2012.
+Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal
+Fua, and Sabine Süsstrunk. IEEE Transactions on Pattern Analysis
+and Machine Intelligence, 34(11), 2274 - 2282. <br>
+<a href="http://ivrl.epfl.ch/research/superpixels">SLIC(0) website</a>
+
<h2>SEE ALSO</h2>
<em>
<a href="g.gui.iclass.html">g.gui.iclass</a>,
Modified: grass-addons/grass7/imagery/i.superpixels.slic/main.c
===================================================================
--- grass-addons/grass7/imagery/i.superpixels.slic/main.c 2017-02-04 17:24:56 UTC (rev 70485)
+++ grass-addons/grass7/imagery/i.superpixels.slic/main.c 2017-02-04 20:57:58 UTC (rev 70486)
@@ -37,6 +37,9 @@
int SLIC_EnforceLabelConnectivity(struct cache *k_seg, int ncols, int nrows,
struct cache *nk_seg, int minsize);
+int perturb_seeds(struct cache *bands_seg, int nbands, DCELL **kseedsb,
+ double *kseedsx, double *kseedsy, int numk, int offset);
+
int merge_small_clumps(struct cache *bands_seg, int nbands,
struct cache *k_seg, int nlabels,
int diag, int minsize);
@@ -46,7 +49,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_mem;
+ *opt_compactness, *opt_perturb, *opt_minsize, *opt_mem;
struct Option *opt_out; /* option for output */
struct Flag *flag_n;
@@ -81,7 +84,8 @@
double xe, ye;
int x, y, x1, y1, x2, y2, itr;
- short hexgrid, perturbseeds;
+ short int hexgrid;
+ int perturbseeds;
int seedx, seedy;
int *clustersize;
@@ -132,6 +136,15 @@
opt_step->description = _("A step size > 0 overrides the number of super pixels");
opt_step->answer = "0";
+ opt_perturb = G_define_option();
+ opt_perturb->key = "perturb";
+ opt_perturb->type = TYPE_INTEGER;
+ opt_perturb->required = NO;
+ opt_perturb->options = "0-100";
+ opt_perturb->label = _("Perturb initial super pixel centers");
+ opt_perturb->description = _("Percent of intitial superpixel radius");
+ opt_perturb->answer = "0";
+
opt_compactness = G_define_option();
opt_compactness->key = "compactness";
opt_compactness->type = TYPE_DOUBLE;
@@ -246,34 +259,33 @@
ncols = Rast_window_cols();
/* determine seed grid */
- offset = step;
superpixelsize = step * step;
if (step < 5) {
superpixelsize = 0.5 + (double)nrows * ncols / n_super_pixels;
- offset = sqrt((double)superpixelsize) + 0.5;
+ step = sqrt((double)superpixelsize) + 0.5;
}
- xstrips = (0.5 + (double)ncols / offset);
- ystrips = (0.5 + (double)nrows / offset);
+ xstrips = (0.5 + (double)ncols / step);
+ ystrips = (0.5 + (double)nrows / step);
- xerr = ncols - offset * xstrips;
+ xerr = ncols - step * xstrips;
if (xerr < 0) {
xstrips--;
- xerr = ncols - offset * xstrips;
+ xerr = ncols - step * xstrips;
}
- yerr = nrows - offset * ystrips;
+ yerr = nrows - step * ystrips;
if (yerr < 0) {
ystrips--;
- yerr = nrows - offset * ystrips;
+ yerr = nrows - step * ystrips;
}
xerrperstrip = (double)xerr / xstrips;
yerrperstrip = (double)yerr / ystrips;
- xoff = offset / 2;
- yoff = offset / 2;
+ xoff = step / 2;
+ yoff = step / 2;
numk = xstrips * ystrips;
@@ -432,13 +444,13 @@
ye = y * yerrperstrip;
for (x = 0; x < xstrips; x++) {
xe = x * xerrperstrip;
- seedx = (x * offset + xoff + xe);
+ seedx = (x * step + xoff + xe);
if (hexgrid > 0) {
- seedx = x * offset + (xoff << (y & 0x1)) + xe;
+ seedx = x * step + (xoff << (y & 0x1)) + xe;
seedx = MIN(ncols - 1, seedx);
} /* for hex grid sampling */
- seedy = (y * offset + yoff + ye);
+ seedy = (y * step + yoff + ye);
cache_get(&bands_seg, pdata, seedy, seedx);
if (!Rast_is_d_null_value(pdata)) {
@@ -454,8 +466,24 @@
if (k != numk)
G_warning(_("Initialized %d of %d seeds"), k, numk);
+ perturbseeds = 0;
+ if (opt_perturb->answer) {
+ if (sscanf(opt_perturb->answer, "%d", &perturbseeds) != 1) {
+ G_fatal_error(_("Illegal value for <%s>"),
+ opt_perturb->answer);
+ }
+ if (perturbseeds > 0) {
+ perturbseeds = (step - 1) * perturbseeds / (2 * 100);
+ if (perturbseeds == 0)
+ perturbseeds = 1;
+ perturb_seeds(&bands_seg, nbands, kseedsb, kseedsx, kseedsy,
+ numk, perturbseeds);
+ }
+ }
+
maxdistspec = maxdistspecprev = 0;
+ offset = step; /* offset could also be step * 1.5 */
/* magic factor */
invwt = 0.1 * compactness / (offset * offset);
@@ -793,3 +821,131 @@
return label;
}
+
+int perturb_seeds(struct cache *bands_seg, int nbands, DCELL **kseedsb,
+ double *kseedsx, double *kseedsy, int numk, int offset)
+{
+ int row, col, rown, coln, nrows, ncols, k, b;
+ int nperturbed;
+ double g, gmin, d, ds;
+ int gn;
+ int x, y, xmin, ymin;
+ DCELL *pdata, *pdatan;
+
+ G_message(_("Perturbing seeds..."));
+ G_verbose_message(_("Perturbing distance : %d"), offset);
+
+ nrows = Rast_window_rows();
+ ncols = Rast_window_cols();
+
+ pdata = G_malloc(sizeof(DCELL) * nbands);
+ pdatan = G_malloc(sizeof(DCELL) * nbands);
+
+ nperturbed = 0;
+ for (k = 0; k < numk; k++) {
+ x = kseedsx[k];
+ y = kseedsy[k];
+ xmin = x;
+ ymin = y;
+
+ gmin = -1;
+ for (row = y - offset; row <= y + offset; row++) {
+ if (row < 0 || row >= nrows)
+ continue;
+ for (col = x - offset; col <= x + offset; col++) {
+ if (col < 0 || col >= ncols)
+ continue;
+
+ cache_get(bands_seg, pdata, row, col);
+
+ if (Rast_is_d_null_value(pdata))
+ continue;
+
+ /* get gradient */
+ g = 0;
+ gn = 0;
+
+ rown = row - 1;
+ coln = col;
+ if (rown >= 0 && rown < nrows && coln >= 0 && coln < ncols) {
+ cache_get(bands_seg, pdatan, rown, coln);
+ if (!Rast_is_d_null_value(pdatan)) {
+ ds = 0;
+ for (b = 0; b < nbands; b++) {
+ d = pdata[b] - pdatan[b];
+ ds += d * d;
+ }
+ g += ds / nbands;
+ gn++;
+ }
+ }
+ rown = row + 1;
+ coln = col;
+ if (rown >= 0 && rown < nrows && coln >= 0 && coln < ncols) {
+ cache_get(bands_seg, pdatan, rown, coln);
+ if (!Rast_is_d_null_value(pdatan)) {
+ ds = 0;
+ for (b = 0; b < nbands; b++) {
+ d = pdata[b] - pdatan[b];
+ ds += d * d;
+ }
+ g += ds / nbands;
+ gn++;
+ }
+ }
+ rown = row;
+ coln = col - 1;
+ if (rown >= 0 && rown < nrows && coln >= 0 && coln < ncols) {
+ cache_get(bands_seg, pdatan, rown, coln);
+ if (!Rast_is_d_null_value(pdatan)) {
+ ds = 0;
+ for (b = 0; b < nbands; b++) {
+ d = pdata[b] - pdatan[b];
+ ds += d * d;
+ }
+ g += ds / nbands;
+ gn++;
+ }
+ }
+ rown = row;
+ coln = col + 1;
+ if (rown >= 0 && rown < nrows && coln >= 0 && coln < ncols) {
+ cache_get(bands_seg, pdatan, rown, coln);
+ if (!Rast_is_d_null_value(pdatan)) {
+ ds = 0;
+ for (b = 0; b < nbands; b++) {
+ d = pdata[b] - pdatan[b];
+ ds += d * d;
+ }
+ g += ds / nbands;
+ gn++;
+ }
+ }
+
+ if (gn > 0) {
+ g /= gn;
+ if (gmin == -1 || gmin > g) {
+ gmin = g;
+ ymin = row;
+ xmin = col;
+ }
+ }
+ }
+ }
+ if (xmin != x || ymin != y) {
+ kseedsx[k] = xmin;
+ kseedsy[k] = ymin;
+ cache_get(bands_seg, pdatan, ymin, xmin);
+ memcpy(kseedsb[k], pdatan, sizeof(DCELL) * nbands);
+ nperturbed++;
+ }
+ }
+
+ G_free(pdata);
+ G_free(pdatan);
+
+ G_verbose_message(_("%d of %d seeds have been perturbed"),
+ nperturbed, numk);
+
+ return nperturbed;
+}
More information about the grass-commit
mailing list