[GRASS-SVN] r69838 - grass/trunk/raster/r.texture

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Nov 16 12:31:35 PST 2016


Author: mmetz
Date: 2016-11-16 12:31:35 -0800 (Wed, 16 Nov 2016)
New Revision: 69838

Modified:
   grass/trunk/raster/r.texture/h_measure.c
   grass/trunk/raster/r.texture/h_measure.h
   grass/trunk/raster/r.texture/main.c
   grass/trunk/raster/r.texture/r.texture.html
Log:
r.texture: fix #3210, #2315, clean up code

Modified: grass/trunk/raster/r.texture/h_measure.c
===================================================================
--- grass/trunk/raster/r.texture/h_measure.c	2016-11-16 10:49:59 UTC (rev 69837)
+++ grass/trunk/raster/r.texture/h_measure.c	2016-11-16 20:31:35 UTC (rev 69838)
@@ -6,6 +6,7 @@
  *               with hints from: 
  * 			prof. Giulio Antoniol - antoniol at ieee.org
  * 			prof. Michele Ceccarelli - ceccarelli at unisannio.it
+ *               Markus Metz (optimization and bug fixes)
  *
  * PURPOSE:      Create map raster with textural features.
  *
@@ -28,9 +29,6 @@
 #include <grass/raster.h>
 #include <grass/glocale.h>
 
-#define RADIX 2.0
-#define EPSILON 0.000000001
-
 #define BL  "Direction             "
 #define F1  "Angular Second Moment "
 #define F2  "Contrast              "
@@ -46,28 +44,25 @@
 #define F12 "Measure of Correlation-1 "
 #define F13 "Measure of Correlation-2 "
 
-#define SIGN(x,y) ((y)<0 ? -fabs(x) : fabs(x))
-#define SWAP(a,b) {y=(a);(a)=(b);(b)=y;}
-
 #define PGM_MAXMAXVAL 255
 #define MAX_MATRIX_SIZE 512
 
 float **matrix(int nr, int nc);
 float *vector(int n);
 
-float f1_asm(float **P, int Ng);
-float f2_contrast(float **P, int Ng);
-float f3_corr(float **P, int Ng);
-float f4_var(float **P, int Ng);
-float f5_idm(float **P, int Ng);
-float f6_savg(float **P, int Ng);
-float f7_svar(float **P, int Ng, double S);
-float f8_sentropy(float **P, int Ng);
-float f9_entropy(float **P, int Ng);
-float f10_dvar(float **P, int Ng);
-float f11_dentropy(float **P, int Ng);
-float f12_icorr(float **P, int Ng);
-float f13_icorr(float **P, int Ng);
+float f1_asm(void);
+float f2_contrast(void);
+float f3_corr(void);
+float f4_var(void);
+float f5_idm(void);
+float f6_savg(void);
+float f7_svar(void);
+float f8_sentropy(void);
+float f9_entropy(void);
+float f10_dvar(void);
+float f11_dentropy(void);
+float f12_icorr(void);
+float f13_icorr(void);
 
 static float **P_matrix = NULL;
 static float **P_matrix0 = NULL;
@@ -76,16 +71,15 @@
 static float **P_matrix135 = NULL;
 
 int tone[PGM_MAXMAXVAL + 1];
-static int tones = 0;
-static float sentropy = 0.0;
+static int Ng = 0;
 static float *px, *py;
 static float Pxpys[2 * PGM_MAXMAXVAL + 2];
 static float Pxpyd[2 * PGM_MAXMAXVAL + 2];
 
 
-void alloc_vars(int size, int dist)
+void alloc_vars(int size)
 {
-    int Ng;
+    int msize2;
 
     /* Allocate memory for gray-tone spatial dependence matrix */
     P_matrix0 = matrix(MAX_MATRIX_SIZE + 1, MAX_MATRIX_SIZE + 1);
@@ -94,104 +88,138 @@
     P_matrix135 = matrix(MAX_MATRIX_SIZE + 1, MAX_MATRIX_SIZE + 1);
 
     if (size * size < 256)
-	Ng = size * size;
+	msize2 = size * size;
     else
-	Ng = 256;
+	msize2 = 256;
 
-    px = vector(Ng + 1);
-    py = vector(Ng + 1);
+    px = vector(msize2 + 1);
+    py = vector(msize2 + 1);
 }
 
+static int bsearch_gray(int *array, int n, int val)
+{
+    int lo, hi, mid;
+
+    lo = 0;
+    hi = n - 1;
+
+    while (lo <= hi) {
+	mid = (lo + hi) >> 1;
+	
+	if (array[mid] == val)
+	    return mid;
+
+	if (array[mid] > val)
+	    hi = mid - 1;
+	else
+	    lo = mid + 1;
+    }
+
+    return -1;
+}
+
 int set_vars(int **grays, int curr_row, int curr_col,
                 int size, int offset, int t_d)
 {
     int R0, R45, R90, R135, x, y;
     int row, col, row2, col2, rows, cols;
     int itone, jtone;
+    int cnt;
 
     rows = cols = size;
 
     /* Determine the number of different gray scales (not maxval) */
     for (row = 0; row <= PGM_MAXMAXVAL; row++)
 	tone[row] = -1;
+    cnt = 0;
     for (row = curr_row - offset; row <= curr_row + offset; row++) {
 	for (col = curr_col - offset; col <= curr_col + offset; col++) {
 	    if (grays[row][col] < 0) {	/* No data pixel found */
-		return 0;
+		continue;
 	    }
 	    if (grays[row][col] > PGM_MAXMAXVAL)
 		G_fatal_error(_("Too many categories (found: %i, max: %i). "
 				"Try to rescale or reclassify the map"),
 			      grays[row][col], PGM_MAXMAXVAL);
 	    tone[grays[row][col]] = grays[row][col];
+	    cnt++;
 	}
     }
+    /* what is the minimum number of pixels 
+     * to get reasonable texture measurements ? */
+    if (cnt < t_d * t_d * 4)
+	return 0;
 
     /* Collapse array, taking out all zero values */
-    tones = 0;
+    Ng = 0;
     for (row = 0; row <= PGM_MAXMAXVAL; row++) {
 	if (tone[row] != -1)
-	    tone[tones++] = tone[row];
+	    tone[Ng++] = tone[row];
     }
 
     /* Now array contains only the gray levels present (in ascending order) */
 
-    for (row = 0; row < tones; row++)
-	for (col = 0; col < tones; col++) {
+    for (row = 0; row < Ng; row++)
+	for (col = 0; col < Ng; col++) {
 	    P_matrix0[row][col] = P_matrix45[row][col] = 0;
 	    P_matrix90[row][col] = P_matrix135[row][col] = 0;
 	}
 
+    /* Find normalizing constants */
+    /* not correct in case of NULL cells: */
+    /*
+    R0 = 2 * rows * (cols - t_d);
+    R45 = 2 * (rows - t_d) * (cols - t_d);
+    R90 = 2 * (rows - t_d) * cols;
+    R135 = R45;
+    */
+
+    /* count actual cooccurrences for each angle */
+    R0 = R45 = R90 = R135 = 0;
+
     /* Find gray-tone spatial dependence matrix */
-
     for (row = 0; row < rows; row++) {
 	row2 = curr_row - offset + row;
 	for (col = 0; col < cols; col++) {
 	    col2 = curr_col - offset + col;
-	    x = 0;
-	    while (tone[x] != grays[row2][col2])
-		x++;
-	    if (col + t_d < cols) {
-		y = 0;
-		while (tone[y] != grays[row2][col2 + t_d])
-		    y++;
+	    if (grays[row2][col2] < 0)
+		continue;
+	    x = bsearch_gray(tone, Ng, grays[row2][col2]);
+	    if (col + t_d < cols &&
+	        grays[row2][col2 + t_d] >= 0) {
+		y = bsearch_gray(tone, Ng, grays[row2][col2 + t_d]);
 		P_matrix0[x][y]++;
 		P_matrix0[y][x]++;
+		R0 += 2;
 	    }
-	    if (row + t_d < rows) {
-		y = 0;
-		while (tone[y] != grays[row2 + t_d][col2])
-		    y++;
+	    if (row + t_d < rows &&
+	        grays[row2 + t_d][col2] >= 0) {
+		y = bsearch_gray(tone, Ng, grays[row2 + t_d][col2]);
 		P_matrix90[x][y]++;
 		P_matrix90[y][x]++;
+		R90 += 2;
 	    }
-	    if (row + t_d < rows && col - t_d >= 0) {
-		y = 0;
-		while (tone[y] != grays[row2 + t_d][col2 - t_d])
-		    y++;
+	    if (row + t_d < rows && col - t_d >= 0 &&
+	        grays[row2 + t_d][col2 - t_d] >= 0) {
+		y = bsearch_gray(tone, Ng, grays[row2 + t_d][col2 - t_d]);
 		P_matrix45[x][y]++;
 		P_matrix45[y][x]++;
+		R45 += 2;
 	    }
-	    if (row + t_d < rows && col + t_d < cols) {
-		y = 0;
-		while (tone[y] != grays[row2 + t_d][col2 + t_d])
-		    y++;
+	    if (row + t_d < rows && col + t_d < cols &&
+	        grays[row2 + t_d][col2 + t_d] >= 0) {
+		y = bsearch_gray(tone, Ng, grays[row2 + t_d][col2 + t_d]);
 		P_matrix135[x][y]++;
 		P_matrix135[y][x]++;
+		R135 += 2;
 	    }
 	}
     }
     /* Gray-tone spatial dependence matrices are complete */
 
-    /* Find normalizing constants */
-    R0 = 2 * rows * (cols - 1);
-    R45 = 2 * (rows - 1) * (cols - 1);
-    R90 = 2 * (rows - 1) * cols;
-    R135 = R45;
-
     /* Normalize gray-tone spatial dependence matrix */
-    for (itone = 0; itone < tones; itone++) {
-	for (jtone = 0; jtone < tones; jtone++) {
+    for (itone = 0; itone < Ng; itone++) {
+	for (jtone = 0; jtone < Ng; jtone++) {
 	    P_matrix0[itone][jtone] /= R0;
 	    P_matrix45[itone][jtone] /= R45;
 	    P_matrix90[itone][jtone] /= R90;
@@ -202,10 +230,10 @@
     return 1;
 }
 
-int set_angle_vars(int angle, int have_px, int have_py, int have_sentr,
+int set_angle_vars(int angle, int have_px, int have_py,
                    int have_pxpys, int have_pxpyd)
 {
-    int i, j, Ng;
+    int i, j;
     float **P;
 
     switch (angle) {
@@ -223,10 +251,6 @@
 	break;
     }
 
-    if (have_sentr)
-	sentropy = f8_sentropy(P_matrix, tones);
-
-    Ng = tones;
     P = P_matrix;
 
     /*
@@ -276,69 +300,69 @@
 {
     switch (t_m) {
 	/* Angular Second Moment */
-    case 0:
-	return (f1_asm(P_matrix, tones));
+    case 1:
+	return (f1_asm());
 	break;
 
     /* Contrast */
-    case 1:
-	return (f2_contrast(P_matrix, tones));
+    case 2:
+	return (f2_contrast());
 	break;
 
     /* Correlation */
-    case 2:
-	return (f3_corr(P_matrix, tones));
+    case 3:
+	return (f3_corr());
 	break;
 
     /* Variance */
-    case 3:
-	return (f4_var(P_matrix, tones));
+    case 4:
+	return (f4_var());
 	break;
 
     /* Inverse Diff Moment */
-    case 4:
-	return (f5_idm(P_matrix, tones));
+    case 5:
+	return (f5_idm());
 	break;
 
     /* Sum Average */
-    case 5:
-	return (f6_savg(P_matrix, tones));
-	break;
-
-    /* Sum Entropy */
     case 6:
-	return (sentropy);
+	return (f6_savg());
 	break;
 
     /* Sum Variance */
     case 7:
-	return (f7_svar(P_matrix, tones, sentropy));
+	return (f7_svar());
 	break;
 
-    /* Entropy */
+    /* Sum Entropy */
     case 8:
-	return (f9_entropy(P_matrix, tones));
+	return (f8_sentropy());
 	break;
 
-    /* Difference Variance */
+    /* Entropy */
     case 9:
-	return (f10_dvar(P_matrix, tones));
+	return (f9_entropy());
 	break;
 
-    /* Difference Entropy */
+    /* Difference Variance */
     case 10:
-	return (f11_dentropy(P_matrix, tones));
+	return (f10_dvar());
 	break;
 
-    /* Measure of Correlation-1 */
+    /* Difference Entropy */
     case 11:
-	return (f12_icorr(P_matrix, tones));
+	return (f11_dentropy());
 	break;
 
-    /* Measure of Correlation-2 */
+    /* Measure of Correlation-1 */
     case 12:
-	return (f13_icorr(P_matrix, tones));
+	return (f12_icorr());
 	break;
+
+    /* Measure of Correlation-2 */
+    case 13:
+	return (f13_icorr());
+	break;
     }
 
     return 0;
@@ -361,10 +385,11 @@
  * gray-tone transitions. Hence the P matrix for such an image will have
  * fewer entries of large magnitude.
  */
-float f1_asm(float **P, int Ng)
+float f1_asm(void)
 {
     int i, j;
     float sum = 0;
+    float **P = P_matrix;
 
     for (i = 0; i < Ng; i++)
 	for (j = 0; j < Ng; j++)
@@ -379,22 +404,36 @@
  * measure of the contrast or the amount of local variations present in an
  * image.
  */
-float f2_contrast(float **P, int Ng)
+float f2_contrast(void)
 {
-    int i, j, n;
+    int i, j /*, n */;
     float sum, bigsum = 0;
+    float **P = P_matrix;
 
+    /*
     for (n = 0; n < Ng; n++) {
 	sum = 0;
 	for (i = 0; i < Ng; i++) {
 	    for (j = 0; j < Ng; j++) {
-		if ((i - j) == n || (j - i) == n) {
+		if ((tone[i] - tone[j]) == tone[n] ||
+		    (tone[j] - tone[i]) == tone[n]) {
 		    sum += P[i][j];
 		}
 	    }
 	}
-	bigsum += n * n * sum;
+	bigsum += tone[n] * tone[n] * sum;
     }
+    */
+
+    /* two-loop version */
+    for (i = 0; i < Ng; i++) {
+	for (j = 0; j < Ng; j++) {
+	    if (i != j) {
+		sum += P[i][j] * (tone[i] - tone[j]) * (tone[i] - tone[j]);
+	    }
+	}
+    }
+
     return bigsum;
 }
 
@@ -403,13 +442,13 @@
  * This correlation feature is a measure of gray-tone linear-dependencies
  * in the image.
  */
-float f3_corr(float **P, int Ng)
+float f3_corr(void)
 {
     int i, j;
-    float sum_sqrx = 0, sum_sqry = 0, tmp = 0;
-    float meanx = 0, meany = 0, stddevx, stddevy;
+    float sum_sqr = 0, tmp = 0;
+    float mean = 0, stddev;
+    float **P = P_matrix;
 
-
     /* Now calculate the means and standard deviations of px and py */
 
     /*- fix supplied by J. Michael Christensen, 21 Jun 1991 */
@@ -418,25 +457,23 @@
      *     after realizing that meanx=meany and stddevx=stddevy
      */
     for (i = 0; i < Ng; i++) {
-	meanx += px[i] * i;
-	sum_sqrx += px[i] * i * i;
+	mean += px[i] * tone[i];
+	sum_sqr += px[i] * tone[i] * tone[i];
 
 	for (j = 0; j < Ng; j++)
-	    tmp += i * j * P[i][j];
+	    tmp += tone[i] * tone[j] * P[i][j];
     }
-    meany = meanx;
-    sum_sqry = sum_sqrx;
-    stddevx = sqrt(sum_sqrx - (meanx * meanx));
-    stddevy = stddevx;
+    stddev = sqrt(sum_sqr - (mean * mean));
 
-    return (tmp - meanx * meany) / (stddevx * stddevy);
+    return (tmp - mean * mean) / (stddev * stddev);
 }
 
 /* Sum of Squares: Variance */
-float f4_var(float **P, int Ng)
+float f4_var(void)
 {
     int i, j;
     float mean = 0, var = 0;
+    float **P = P_matrix;
 
     /*- Corrected by James Darrell McCauley, 16 Aug 1991
      *  calculates the mean intensity level instead of the mean of
@@ -444,73 +481,102 @@
      */
     for (i = 0; i < Ng; i++)
 	for (j = 0; j < Ng; j++)
-	    mean += i * P[i][j];
+	    mean += tone[i] * P[i][j];
 
     for (i = 0; i < Ng; i++)
 	for (j = 0; j < Ng; j++)
-	    var += (i + 1 - mean) * (i + 1 - mean) * P[i][j];
+	    var += (tone[i] - mean) * (tone[j] - mean) * P[i][j];
 
     return var;
 }
 
 /* Inverse Difference Moment */
-float f5_idm(float **P, int Ng)
+float f5_idm(void)
 {
     int i, j;
     float idm = 0;
+    float **P = P_matrix;
 
     for (i = 0; i < Ng; i++)
 	for (j = 0; j < Ng; j++)
-	    idm += P[i][j] / (1 + (i - j) * (i - j));
+	    idm += P[i][j] / (1 + (tone[i] - tone[j]) * (tone[i] - tone[j]));
 
     return idm;
 }
 
 /* Sum Average */
-float f6_savg(float **P, int Ng)
+float f6_savg(void)
 {
-    int i;
+    int i, j, k;
     float savg = 0;
+    float *P = Pxpys;
 
+    /*
     for (i = 0; i < 2 * Ng - 1; i++)
 	savg += (i + 2) * Pxpys[i];
+    */
 
+    for (i = 0; i < Ng; i++) {
+	for (j = 0; j < Ng; j++) {
+	    k = i + j;
+	    savg += (tone[i] + tone[j]) * P[k];
+	}
+    }
+
     return savg;
 }
 
 /* Sum Variance */
-float f7_svar(float **P, int Ng, double S)
+float f7_svar(void)
 {
-    int i;
+    int i, j, k;
     float var = 0;
+    float *P = Pxpys;
+    float savg = f6_savg();
+    float tmp;
 
+    /*
     for (i = 0; i < 2 * Ng - 1; i++)
-	var += (i + 2 - S) * (i + 2 - S) * Pxpys[i];
+	var += (i + 2 - savg) * (i + 2 - savg) * Pxpys[i];
+    */
 
+    for (i = 0; i < Ng; i++) {
+	for (j = 0; j < Ng; j++) {
+	    k = i + j;
+	    tmp = tone[i] + tone[j] - savg;
+	    var += tmp * tmp * P[k];
+	}
+    }
+
     return var;
 }
 
 /* Sum Entropy */
-float f8_sentropy(float **P, int Ng)
+float f8_sentropy(void)
 {
     int i;
     float sentr = 0;
+    float *P = Pxpys;
 
-    for (i = 0; i < 2 * Ng - 1; i++)
-	sentr -= Pxpys[i] * log10(Pxpys[i] + EPSILON);
+    for (i = 0; i < 2 * Ng - 1; i++) {
+	if (P[i] > 0)
+	    sentr -= P[i] * log2(P[i]);
+    }
 
     return sentr;
 }
 
 /* Entropy */
-float f9_entropy(float **P, int Ng)
+float f9_entropy(void)
 {
     int i, j;
     float entropy = 0;
+    float **P = P_matrix;
 
     for (i = 0; i < Ng; i++) {
 	for (j = 0; j < Ng; j++) {
-	    entropy += P[i][j] * log10(P[i][j] + EPSILON);
+	    if (P[i][j] > 0)
+		entropy += P[i][j] * log2(P[i][j]);
 	}
     }
 
@@ -518,50 +584,60 @@
 }
 
 /* Difference Variance */
-float f10_dvar(float **P, int Ng)
+float f10_dvar(void)
 {
     int i, tmp;
     float sum = 0, sum_sqr = 0, var = 0;
+    float *P = Pxpyd;
 
     /* Now calculate the variance of Pxpy (Px-y) */
     for (i = 0; i < Ng; i++) {
-	sum += Pxpyd[i];
-	sum_sqr += Pxpyd[i] * Pxpyd[i];
+	sum += P[i];
+	sum_sqr += P[i] * P[i];
     }
-    tmp = Ng * Ng;
+    /* tmp = Ng * Ng; */
+    tmp = (tone[Ng - 1] - tone[0]) * (tone[Ng - 1] - tone[0]);
     var = ((tmp * sum_sqr) - (sum * sum)) / (tmp * tmp);
 
     return var;
 }
 
 /* Difference Entropy */
-float f11_dentropy(float **P, int Ng)
+float f11_dentropy(void)
 {
     int i;
     float sum = 0;
+    float *P = Pxpyd;
 
-    for (i = 0; i < Ng; i++)
-	sum += Pxpyd[i] * log10(Pxpyd[i] + EPSILON);
+    for (i = 0; i < Ng; i++) {
+	if (P[i] > 0)
+	    sum += P[i] * log2(P[i]);
+    }
 
     return -sum;
 }
 
 /* Information Measures of Correlation */
-float f12_icorr(float **P, int Ng)
+float f12_icorr(void)
 {
     int i, j;
     float hx = 0, hy = 0, hxy = 0, hxy1 = 0;
+    float **P = P_matrix;
 
     for (i = 0; i < Ng; i++)
 	for (j = 0; j < Ng; j++) {
-	    hxy1 -= P[i][j] * log10(px[i] * py[j] + EPSILON);
-	    hxy -= P[i][j] * log10(P[i][j] + EPSILON);
+	    if (px[i] * py[j] > 0)
+		hxy1 -= P[i][j] * log2(px[i] * py[j]);
+	    if (P[i][j] > 0)
+		hxy -= P[i][j] * log2(P[i][j]);
 	}
 
     /* Calculate entropies of px and py - is this right? */
     for (i = 0; i < Ng; i++) {
-	hx -= px[i] * log10(px[i] + EPSILON);
-	hy -= py[i] * log10(py[i] + EPSILON);
+	if (px[i] > 0)
+	    hx -= px[i] * log2(px[i]);
+	if (py[i] > 0)
+	    hy -= py[i] * log2(py[i]);
     }
 
     /* fprintf(stderr,"hxy1=%f\thxy=%f\thx=%f\thy=%f\n",hxy1,hxy,hx,hy); */
@@ -569,15 +645,18 @@
 }
 
 /* Information Measures of Correlation */
-float f13_icorr(float **P, int Ng)
+float f13_icorr(void)
 {
     int i, j;
     float hxy = 0, hxy2 = 0;
+    float **P = P_matrix;
 
     for (i = 0; i < Ng; i++) {
 	for (j = 0; j < Ng; j++) {
-	    hxy2 -= px[i] * py[j] * log10(px[i] * py[j] + EPSILON);
-	    hxy -= P[i][j] * log10(P[i][j] + EPSILON);
+	    if (px[i] * py[j] > 0)
+		hxy2 -= px[i] * py[j] * log2(px[i] * py[j]);
+	    if (P[i][j] > 0)
+		hxy -= P[i][j] * log2(P[i][j]);
 	}
     }
 

Modified: grass/trunk/raster/r.texture/h_measure.h
===================================================================
--- grass/trunk/raster/r.texture/h_measure.h	2016-11-16 10:49:59 UTC (rev 69837)
+++ grass/trunk/raster/r.texture/h_measure.h	2016-11-16 20:31:35 UTC (rev 69838)
@@ -24,8 +24,8 @@
  *****************************************************************************/
 
 float h_measure(int);
-void alloc_vars(int, int);
+void alloc_vars(int);
 int set_vars(int **grays, int curr_rrow, int curr_col,
                 int size, int offset, int t_d);
-int set_angle_vars(int angle, int have_px, int have_py, int have_sentr,
+int set_angle_vars(int angle, int have_px, int have_py,
                    int have_pxpys, int have_pxpyd);

Modified: grass/trunk/raster/r.texture/main.c
===================================================================
--- grass/trunk/raster/r.texture/main.c	2016-11-16 10:49:59 UTC (rev 69837)
+++ grass/trunk/raster/r.texture/main.c	2016-11-16 20:31:35 UTC (rev 69838)
@@ -6,6 +6,7 @@
  *               with hints from: 
  * 			prof. Giulio Antoniol - antoniol at ieee.org
  * 			prof. Michele Ceccarelli - ceccarelli at unisannio.it
+ *               Markus Metz (optimization and bug fixes)
  *
  * PURPOSE:      Create map raster with textural features.
  *
@@ -40,19 +41,19 @@
 
 /* modify this table to add new measures */
 static struct menu menu[] = {
-    {"asm",      "Angular Second Moment",    "_ASM",   0,  0},
-    {"contrast", "Contrast",                 "_Contr", 0,  1},
-    {"corr",     "Correlation",              "_Corr",  0,  2},
-    {"var",      "Variance",                 "_Var",   0,  3},
-    {"idm",      "Inverse Diff Moment",      "_IDM",   0,  4},
-    {"sa",       "Sum Average",              "_SA",    0,  5},
-    {"se",       "Sum Entropy",              "_SE",    0,  6},
+    {"asm",      "Angular Second Moment",    "_ASM",   0,  1},
+    {"contrast", "Contrast",                 "_Contr", 0,  2},
+    {"corr",     "Correlation",              "_Corr",  0,  3},
+    {"var",      "Variance",                 "_Var",   0,  4},
+    {"idm",      "Inverse Diff Moment",      "_IDM",   0,  5},
+    {"sa",       "Sum Average",              "_SA",    0,  6},
     {"sv",       "Sum Variance",             "_SV",    0,  7},
-    {"entr",     "Entropy",                  "_Entr",  0,  8},
-    {"dv",       "Difference Variance",      "_DV",    0,  9},
-    {"de",       "Difference Entropy",       "_DE",    0, 10},
-    {"moc1",     "Measure of Correlation-1", "_MOC-1", 0, 11},
-    {"moc2",     "Measure of Correlation-2", "_MOC-2", 0, 12},
+    {"se",       "Sum Entropy",              "_SE",    0,  8},
+    {"entr",     "Entropy",                  "_Entr",  0,  9},
+    {"dv",       "Difference Variance",      "_DV",    0, 10},
+    {"de",       "Difference Entropy",       "_DE",    0, 11},
+    {"moc1",     "Measure of Correlation-1", "_MOC-1", 0, 12},
+    {"moc2",     "Measure of Correlation-2", "_MOC-2", 0, 13},
     {NULL, NULL, NULL, 0, -1}
 };
 
@@ -86,9 +87,9 @@
     FCELL measure;		/* Containing measure done */
     int dist, size;	/* dist = value of distance, size = s. of moving window */
     int offset;
-    int have_px, have_py, have_sentr, have_pxpys, have_pxpyd;
+    int have_px, have_py, have_pxpys, have_pxpyd;
     int infd, *outfd;
-    RASTER_MAP_TYPE data_type, out_data_type;
+    RASTER_MAP_TYPE out_data_type;
     struct GModule *module;
     struct Option *opt_input, *opt_output, *opt_size, *opt_dist, *opt_measure;
     struct Flag *flag_ind, *flag_all;
@@ -127,7 +128,8 @@
     opt_dist->key_desc = "value";
     opt_dist->type = TYPE_INTEGER;
     opt_dist->required = NO;
-    opt_dist->description = _("The distance between two samples (>= 1)");
+    opt_dist->label = _("The distance between two samples (>= 1)");
+    opt_dist->description = _("The distance must be smaller than the size of the moving window");
     opt_dist->answer = "1";
 
     for (i = 0; menu[i].name; i++) {
@@ -166,6 +168,8 @@
     dist = atoi(opt_dist->answer);
     if (dist <= 0)
 	G_fatal_error(_("The distance between two samples must be > 0"));
+    if (dist >= size)
+	G_fatal_error(_("The distance between two samples must be smaller than the size of the moving window"));
 
     n_measures = 0;
     if (flag_all->answer) {
@@ -192,7 +196,7 @@
     j = 0;
     for (i = 0; menu[i].name; i++) {
 	if (menu[i].useme == 1) {
-	    measure_idx[j] = menu[i].idx;
+	    measure_idx[j] = i;
 	    j++;
 	}
     }
@@ -206,10 +210,6 @@
 	have_py = 1;
     else
 	have_py = 0;
-    if (menu[6].useme || menu[7].useme)
-	have_sentr = 1;
-    else
-	have_sentr = 0;
     if (menu[5].useme || menu[6].useme || menu[7].useme)
 	have_pxpys = 1;
     else
@@ -221,9 +221,6 @@
 
     infd = Rast_open_old(name, "");
 
-    /* determine the inputmap type (CELL/FCELL/DCELL) */
-    data_type = Rast_get_map_type(infd);
-
     Rast_get_cellhd(name, "", &cellhd);
 
     out_data_type = FCELL_TYPE;
@@ -328,7 +325,7 @@
         "Calculating %d texture measures", n_measures), n_measures);
     else
 	G_message(_("Calculating %s..."), menu[measure_idx[0]].desc);
-    alloc_vars(size, dist);
+    alloc_vars(size);
     for (row = first_row; row < last_row; row++) {
 	G_percent(row, nrows, 2);
 
@@ -346,11 +343,11 @@
 
 	    /* for all angles (0, 45, 90, 135) */
 	    for (i = 0; i < 4; i++) {
-		set_angle_vars(i, have_px, have_py, have_sentr, have_pxpys, have_pxpyd);
+		set_angle_vars(i, have_px, have_py, have_pxpys, have_pxpyd);
 		/* for all requested textural measures */
 		for (j = 0; j < n_measures; j++) {
 
-		    measure = (FCELL) h_measure(measure_idx[j]);
+		    measure = (FCELL) h_measure(menu[measure_idx[j]].idx);
 
 		    if (flag_ind->answer) {
 			/* output for each angle separately */

Modified: grass/trunk/raster/r.texture/r.texture.html
===================================================================
--- grass/trunk/raster/r.texture/r.texture.html	2016-11-16 10:49:59 UTC (rev 69837)
+++ grass/trunk/raster/r.texture/r.texture.html	2016-11-16 20:31:35 UTC (rev 69838)
@@ -8,14 +8,21 @@
 <em>r.texture</em> assumes grey levels ranging from 0 to 255 as input. 
 The input is automatically rescaled to 0 to 255 if the input map range is outside
 of this range.
+
 <p>
+In order to reduce noise in the input data, and to speed up processing, 
+the input map can be recoded using equal-probability quantization. 
+Quantization rules for <em>r.recode</em> can be generated with 
+<em>r.quantile -r</em> using e.g 16 or 32 quantiles (see example below). 
+
+<p>
 In general, several variables constitute texture: differences in grey level values,
 coarseness as scale of grey level differences, presence or lack of directionality
 and regular patterns. A texture can be characterized by tone (grey level intensity
 properties) and structure (spatial relationships). Since textures are highly scale
 dependent, hierarchical textures may occur.
+
 <p>
-    
 <em>r.texture</em> reads a GRASS raster map as input and calculates
 textural features based on spatial dependence matrices for north-south,
 east-west, northwest, and southwest directions using a side by side
@@ -122,6 +129,15 @@
 This calculates four maps (requested texture at four orientations):
 ortho_texture_ASM_0, ortho_texture_ASM_45, ortho_texture_ASM_90, ortho_texture_ASM_135.
 
+Reducing the number of gray levels (equal-probability quantizing):
+
+<div class="code"><pre>
+g.region -p rast=ortho_2001_t792_1m
+r.quantile in=ortho_2001_t792_1m quantiles=16 -r | r.recode in=ortho_2001_t792_1m out=ortho_2001_t792_1m_q16 rules=-
+</pre></div>
+
+The recoded raster map can then be used as input for r.texture as before.
+
 <h2>KNOWN ISSUES</h2>
 The program can run incredibly slow for large raster maps.
 
@@ -162,6 +178,7 @@
 <h2>AUTHORS</h2>
 <a href="mailto:antoniol at ieee.org">G. Antoniol</a> - RCOST (Research Centre on Software Technology - Viale Traiano - 82100 Benevento)<br>
 C. Basco -  RCOST (Research Centre on Software Technology - Viale Traiano - 82100 Benevento)<br>
-M. Ceccarelli - Facolta di Scienze, Universita del Sannio, Benevento
+M. Ceccarelli - Facolta di Scienze, Universita del Sannio, Benevento<br>
+Markus Metz
 
 <p><i>Last changed: $Date$</i>



More information about the grass-commit mailing list