2
\file lib/imagery/iclass_statistics.c
4
\brief Imagery library - functions for wx.iclass
6
Computation based on training areas for supervised classification.
7
Based on i.class module (GRASS 6).
9
Computing statistical values (mean, min, max, ...) from given area
10
perimeters for each band.
12
Copyright (C) 1999-2007, 2011 by the GRASS Development Team
14
This program is free software under the GNU General Public License
15
(>=v2). Read the file COPYING that comes with GRASS for details.
17
\author David Satnik, Central Washington University (original author)
18
\author Markus Neteler <neteler itc.it> (i.class module)
19
\author Bernhard Reiter <bernhard intevation.de> (i.class module)
20
\author Brad Douglas <rez touchofmadness.com>(i.class module)
21
\author Glynn Clements <glynn gclements.plus.com> (i.class module)
22
\author Hamish Bowman <hamish_b yahoo.com> (i.class module)
23
\author Jan-Oliver Wagner <jan intevation.de> (i.class module)
24
\author Anna Kratochvilova <kratochanna gmail.com> (rewriting for wx.iclass)
25
\author Vaclav Petras <wenzeslaus gmail.com> (rewriting for wx.iclass)
30
#include <grass/imagery.h>
31
#include <grass/glocale.h>
32
#include <grass/colors.h>
34
#include "iclass_local_proto.h"
37
\brief Initialize statistics.
39
\param[out] statistics pointer to statistics structure
40
\param category category (class)
41
\param name class name
42
\param color class color
43
\param nstd standard deviation
45
void I_iclass_init_statistics(IClass_statistics * statistics, int category,
46
const char *name, const char *color, float nstd)
48
G_debug(4, "init_statistics() category=%d, name=%s, color=%s, nstd=%f",
49
category, name, color, nstd);
51
statistics->cat = category;
52
statistics->name = G_store(name);
53
statistics->color = G_store(color);
54
statistics->nstd = nstd;
56
statistics->ncells = 0;
57
statistics->nbands = 0;
59
statistics->band_min = NULL;
60
statistics->band_max = NULL;
61
statistics->band_sum = NULL;
62
statistics->band_mean = NULL;
63
statistics->band_stddev = NULL;
64
statistics->band_product = NULL;
65
statistics->band_histo = NULL;
66
statistics->band_range_min = NULL;
67
statistics->band_range_max = NULL;
71
\brief Allocate space for statistics.
73
\param statistics pointer to statistics structure
74
\param nbands number of band files
76
void alloc_statistics(IClass_statistics * statistics, int nbands)
80
G_debug(4, "alloc_statistics()");
82
statistics->nbands = nbands;
84
statistics->band_min = (int *)G_calloc(nbands, sizeof(int));
85
statistics->band_max = (int *)G_calloc(nbands, sizeof(int));
86
statistics->band_sum = (float *)G_calloc(nbands, sizeof(float));
87
statistics->band_mean = (float *)G_calloc(nbands, sizeof(float));
88
statistics->band_stddev = (float *)G_calloc(nbands, sizeof(float));
89
statistics->band_product = (float **)G_calloc(nbands, sizeof(float *));
90
statistics->band_histo = (int **)G_calloc(nbands, sizeof(int *));
91
statistics->band_range_min = (int *)G_calloc(nbands, sizeof(int));
92
statistics->band_range_max = (int *)G_calloc(nbands, sizeof(int));
94
for (i = 0; i < nbands; i++) {
95
statistics->band_product[i] =
96
(float *)G_calloc(nbands, sizeof(float));
97
statistics->band_histo[i] = (int *)G_calloc(MAX_CATS, sizeof(int));
102
\brief Free space allocated for statistics attributes.
104
Frees all allocated arrays in statistics structure.
106
\param statistics pointer to statistics structure
108
void I_iclass_free_statistics(IClass_statistics * statistics)
112
G_debug(4, "free_statistics()");
114
G_free((char *) statistics->name);
115
G_free((char *) statistics->color);
116
G_free(statistics->band_min);
117
G_free(statistics->band_max);
118
G_free(statistics->band_sum);
119
G_free(statistics->band_mean);
120
G_free(statistics->band_stddev);
121
G_free(statistics->band_range_max);
122
G_free(statistics->band_range_min);
125
for (i = 0; i < statistics->nbands; i++) {
126
G_free(statistics->band_histo[i]);
127
G_free(statistics->band_product[i]);
129
G_free(statistics->band_histo);
130
G_free(statistics->band_product);
134
\brief Calculate statistics for all training areas.
136
\param statistics pointer to statistics structure
137
\param perimeters list of all area perimeters
138
\param band_buffer buffer to read band rows into
139
\param band_fd band files descriptors
144
int make_all_statistics(IClass_statistics * statistics,
145
IClass_perimeter_list * perimeters,
146
CELL ** band_buffer, int *band_fd)
148
int i, b, b2, nbands;
150
float mean_value, stddev_value;
152
G_debug(5, "make_all_statistics()");
154
nbands = statistics->nbands;
155
for (b = 0; b < nbands; b++) {
156
statistics->band_sum[b] = 0.0;
157
statistics->band_min[b] = MAX_CATS;
158
statistics->band_max[b] = 0;
159
for (b2 = 0; b2 < nbands; b2++)
160
statistics->band_product[b][b2] = 0.0;
161
for (b2 = 0; b2 < MAX_CATS; b2++)
162
statistics->band_histo[b][b2] = 0;
165
for (i = 0; i < perimeters->nperimeters; i++) {
167
(statistics, &perimeters->perimeters[i], band_buffer, band_fd)) {
171
for (b = 0; b < statistics->nbands; b++) {
172
mean_value = mean(statistics, b);
173
stddev_value = stddev(statistics, b);
175
statistics->band_stddev[b] = stddev_value;
176
statistics->band_mean[b] = mean_value;
178
band_range(statistics, b);
185
\brief Calculate statistics for one training area.
187
\param[out] statistics pointer to statistics structure
188
\param perimeter area perimeter
189
\param band_buffer buffer to read band rows into
190
\param band_fd band files descriptors
195
int make_statistics(IClass_statistics * statistics,
196
IClass_perimeter * perimeter, CELL ** band_buffer,
213
G_debug(5, "make_statistics()");
215
nbands = statistics->nbands;
217
if (perimeter->npoints % 2) {
218
G_warning(_("prepare_signature: outline has odd number of points."));
224
for (i = 1; i < perimeter->npoints; i += 2) {
225
y = perimeter->points[i].y;
226
if (y != perimeter->points[i - 1].y) {
227
G_warning(_("prepare_signature: scan line %d has odd number of points."),
231
read_band_row(band_buffer, band_fd, nbands, y);
233
x0 = perimeter->points[i - 1].x - 1;
234
x1 = perimeter->points[i].x - 1;
237
G_warning(_("signature: perimeter points out of order."));
241
for (x = x0; x <= x1; x++) {
242
ncells++; /* count interior points */
243
for (b = 0; b < nbands; b++) {
244
value = band_buffer[b][x];
245
G_debug(5, "make_statistics() band: %d, read value: %d (max: %d)",
247
if (value < 0 || value > MAX_CATS - 1) {
248
G_warning(_("Data error preparing signatures: value (%d) > num of cats (%d)"),
252
statistics->band_sum[b] += value; /* sum for means */
253
statistics->band_histo[b][value]++; /* histogram */
254
if (statistics->band_min[b] > value)
255
statistics->band_min[b] = value; /* absolute min, max */
256
if (statistics->band_max[b] < value) {
257
statistics->band_max[b] = value;
259
"make_statistics() statistics->band_max[%d]: %d",
260
b, statistics->band_max[b]);
263
for (b2 = 0; b2 <= b; b2++) /* products for variance */
264
statistics->band_product[b][b2] +=
265
value * band_buffer[b2][x];
269
statistics->ncells += ncells;
275
\brief Create raster map based on statistics.
277
\param statistics pointer to statistics structure
278
\param band_buffer buffer to read band rows into
279
\param band_fd band files descriptors
280
\param raster_name name of new raster map
282
void create_raster(IClass_statistics * statistics, CELL ** band_buffer,
283
int *band_fd, const char *raster_name)
295
int row, nrows, ncols;
297
struct Colors raster_colors;
303
nbands = statistics->nbands;
305
/* build new raster based on current signature and Nstd */
307
fd = Rast_open_c_new(raster_name);
308
buffer = Rast_allocate_c_buf();
309
nrows = Rast_window_rows();
310
ncols = Rast_window_cols();
312
for (row = 0; row < nrows; row++) {
313
read_band_row(band_buffer, band_fd, nbands, row);
314
for (col = 0; col < ncols; col++) {
315
buffer[col] = (CELL) 0;
317
for (n = 0; n < nbands; n++) {
318
if (band_buffer[n][col] < statistics->band_range_min[n] ||
319
band_buffer[n][col] > statistics->band_range_max[n]) {
320
/* out of at least 1 range */
324
if (cell_in_ranges) {
325
/* if in range do the assignment */
326
buffer[col] = (CELL) 1;
329
Rast_put_row(fd, buffer, CELL_TYPE);
333
/* generate and write the color table for the mask */
334
Rast_init_colors(&raster_colors);
335
G_str_to_color(statistics->color, &r, &g, &b);
336
Rast_set_c_color((CELL) 1, r, g, b, &raster_colors);
337
Rast_write_colors(raster_name, G_mapset(), &raster_colors);
342
\brief Helper function for computing min and max range in one band.
344
Computing min and max range value (distance from mean
345
dependent on number od std ddevs).
347
\param statistics pointer to statistics structure
348
\param band band index
350
void band_range(IClass_statistics * statistics, int band)
354
dist = statistics->nstd * statistics->band_stddev[band];
355
statistics->band_range_min[band] =
356
statistics->band_mean[band] - dist + 0.5;
357
statistics->band_range_max[band] =
358
statistics->band_mean[band] + dist + 0.5;
362
\brief Helper function for computing mean.
364
Computing mean value of cell category values
365
in one band within training area.
367
\param statistics pointer to statistics structure
368
\param band band index
372
float mean(IClass_statistics * statistics, int band)
374
return statistics->band_sum[band] / statistics->ncells;
378
\brief Helper function for standard deviation.
380
Computing standard deviation of cell category values
381
in one band within training area.
383
\param statistics pointer to statistics structure
384
\param band band index
386
\return standard deviation
388
float stddev(IClass_statistics * statistics, int band)
390
return sqrt(var(statistics, band, band));
394
\brief Helper function for computing variance.
396
Computing variance of cell category values
397
in one band within training area.
399
\param statistics pointer to statistics structure
400
\param band1 band index
401
\param band2 band index
407
float var(IClass_statistics * statistics, int band1, int band2)
415
product = statistics->band_product[band1][band2];
416
mean1 = mean(statistics, band1);
417
mean2 = mean(statistics, band2);
418
n = statistics->ncells;
420
return product / n - mean1 * mean2;
424
\brief Helper function for computing variance for signature file.
426
Computing variance of cell category values
427
in one band within training area. Variance is computed
430
\param statistics pointer to statistics structure
431
\param band1 band index
432
\param band2 band index
438
\todo verify the computation
440
float var_signature(IClass_statistics * statistics, int band1, int band2)
448
product = statistics->band_product[band1][band2];
449
sum1 = statistics->band_sum[band1];
450
sum2 = statistics->band_sum[band2];
451
n = statistics->ncells;
453
return (product - sum1 * sum2 / n) / (n - 1);
458
\brief Get number of bands.
460
\param statistics pointer to statistics structure
461
\param[out] nbands number of bands
463
void I_iclass_statistics_get_nbands(IClass_statistics * statistics,
466
*nbands = statistics->nbands;
470
\brief Get category (class).
472
\param statistics pointer to statistics structure
473
\param[out] cat category
475
void I_iclass_statistics_get_cat(IClass_statistics * statistics, int *cat)
477
*cat = statistics->cat;
481
\brief Get category (class) name.
483
\note \a name is pointer to already allocated
484
const char * in \a statistics.
485
You should not free it.
487
\param statistics pointer to statistics structure
488
\param[out] name category name
490
void I_iclass_statistics_get_name(IClass_statistics * statistics,
493
*name = statistics->name;
497
\brief Get category (class) color.
499
\note \a color is pointer to already allocated
500
const char * in \a statistics.
501
You should not free it.
503
\param statistics pointer to statistics structure
504
\param[out] color category color
506
void I_iclass_statistics_get_color(IClass_statistics * statistics,
509
*color = statistics->color;
514
\brief Get number of cells in training areas.
516
\param statistics pointer to statistics structure
517
\param[out] ncells number of cells
519
void I_iclass_statistics_get_ncells(IClass_statistics * statistics,
522
*ncells = statistics->ncells;
526
\brief Get the multiplier of standard deviation.
528
\param statistics pointer to statistics structure
529
\param[out] nstd multiplier of standard deviation
531
void I_iclass_statistics_get_nstd(IClass_statistics * statistics, float *nstd)
533
*nstd = statistics->nstd;
537
\brief Set the multiplier of standard deviation.
539
\param statistics pointer to statistics structure
540
\param nstd multiplier of standard deviation
542
void I_iclass_statistics_set_nstd(IClass_statistics * statistics, float nstd)
544
statistics->nstd = nstd;
548
\brief Get minimum value in band.
550
\param statistics pointer to statistics structure
551
\param band band index
552
\param[out] min minimum value
555
\return 0 band index out of range
557
int I_iclass_statistics_get_min(IClass_statistics * statistics, int band,
560
if (band >= statistics->nbands) {
561
G_warning(_("Band index out of range"));
565
*min = statistics->band_min[band];
571
\brief Get maximum value in band.
573
\param statistics pointer to statistics structure
574
\param band band index
575
\param[out] max maximum value
578
\return 0 band index out of range
580
int I_iclass_statistics_get_max(IClass_statistics * statistics, int band,
583
if (band >= statistics->nbands) {
584
G_warning(_("Band index out of range"));
588
*max = statistics->band_max[band];
594
\brief Get sum of values in band.
596
\param statistics pointer to statistics structure
597
\param band band index
601
\return 0 band index out of range
603
int I_iclass_statistics_get_sum(IClass_statistics * statistics, int band,
606
if (band >= statistics->nbands) {
607
G_warning(_("Band index out of range"));
611
*sum = statistics->band_sum[band];
617
\brief Get mean of cell category values in band.
619
\param statistics pointer to statistics structure
620
\param band band index
621
\param[out] mean mean
624
\return 0 band index out of range
626
int I_iclass_statistics_get_mean(IClass_statistics * statistics, int band,
629
if (band >= statistics->nbands) {
630
G_warning(_("Band index out of range"));
634
*mean = statistics->band_mean[band];
640
\brief Get standard deviation of cell category values in band.
642
\param statistics pointer to statistics structure
643
\param band band index
644
\param[out] stddev standard deviation
647
\return 0 band index out of range
649
int I_iclass_statistics_get_stddev(IClass_statistics * statistics, int band,
652
if (band >= statistics->nbands) {
653
G_warning(_("Band index out of range"));
657
*stddev = statistics->band_stddev[band];
663
\brief Get histogram value in band.
665
Each band has one value for each raster cell category.
666
Value is number of cells in category.
668
\param statistics pointer to statistics structure
669
\param band band index
670
\param cat raster cell category
671
\param[out] value number of cells in category
674
\return 0 band index or cell category value out of range
676
int I_iclass_statistics_get_histo(IClass_statistics * statistics, int band,
679
if (band >= statistics->nbands) {
680
G_warning(_("Band index out of range"));
683
if (cat >= MAX_CATS) {
684
G_warning(_("Cell category value out of range"));
688
*value = statistics->band_histo[band][cat];
694
\brief Get product value
696
Product value of two bands is sum of products
697
of cell category values of two bands.
698
Only cells from training areas are taken into account.
700
\param statistics statistics object
701
\param band1 index of first band
702
\param band2 index of second band
703
\param[out] value product value
706
\return 0 band index out of range
708
int I_iclass_statistics_get_product(IClass_statistics * statistics, int band1,
709
int band2, float *value)
711
if (band1 >= statistics->nbands || band2 >= statistics->nbands) {
712
G_warning(_("Band index out of range"));
716
*value = statistics->band_product[band1][band2];
722
\brief Get minimum cell value based on mean and standard deviation for band.
724
\param statistics pointer to statistics structure
725
\param band band index
726
\param[out] min minumum value
729
\return 0 band index out of range
731
int I_iclass_statistics_get_range_min(IClass_statistics * statistics,
734
if (band >= statistics->nbands) {
735
G_warning(_("Band index out of range"));
739
*min = statistics->band_range_min[band];
745
\brief Get maximum cell value based on mean and standard deviation for band.
747
\param statistics pointer to statistics structure
748
\param band band index
749
\param[out] max maximum value
752
\return 0 band index out of range
754
int I_iclass_statistics_get_range_max(IClass_statistics * statistics,
757
if (band >= statistics->nbands) {
758
G_warning(_("Band index out of range"));
762
*max = statistics->band_range_max[band];