GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
iclass_statistics.c
Go to the documentation of this file.
1/*!
2 \file lib/imagery/iclass_statistics.c
3
4 \brief Imagery library - functions for wx.iclass
5
6 Computation based on training areas for supervised classification.
7 Based on i.class module (GRASS 6).
8
9 Computing statistical values (mean, min, max, ...) from given area
10 perimeters for each band.
11
12 Copyright (C) 1999-2007, 2011 by the GRASS Development Team
13
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
16
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)
26 */
27
28#include <math.h>
29
30#include <grass/imagery.h>
31#include <grass/glocale.h>
32#include <grass/colors.h>
33
34#include "iclass_local_proto.h"
35
36/*!
37 \brief Initialize statistics.
38
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
44 */
46 const char *name, const char *color, float nstd)
47{
48 G_debug(4, "init_statistics() category=%d, name=%s, color=%s, nstd=%f",
49 category, name, color, nstd);
50
51 statistics->cat = category;
53 statistics->color = G_store(color);
54 statistics->nstd = nstd;
55
56 statistics->ncells = 0;
57 statistics->nbands = 0;
58
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;
68}
69
70/*!
71 \brief Allocate space for statistics.
72
73 \param statistics pointer to statistics structure
74 \param nbands number of band files
75 */
77{
78 int i;
79
80 G_debug(4, "alloc_statistics()");
81
82 statistics->nbands = nbands;
83
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));
93
94 for (i = 0; i < nbands; i++) {
95 statistics->band_product[i] = (float *)G_calloc(nbands, sizeof(float));
96 statistics->band_histo[i] = (int *)G_calloc(MAX_CATS, sizeof(int));
97 }
98}
99
100/*!
101 \brief Free space allocated for statistics attributes.
102
103 Frees all allocated arrays in statistics structure.
104
105 \param statistics pointer to statistics structure
106 */
108{
109 int i;
110
111 G_debug(4, "free_statistics()");
112
113 G_free((char *)statistics->name);
114 G_free((char *)statistics->color);
115 G_free(statistics->band_min);
116 G_free(statistics->band_max);
117 G_free(statistics->band_sum);
118 G_free(statistics->band_mean);
119 G_free(statistics->band_stddev);
120 G_free(statistics->band_range_max);
121 G_free(statistics->band_range_min);
122
123 for (i = 0; i < statistics->nbands; i++) {
124 G_free(statistics->band_histo[i]);
125 G_free(statistics->band_product[i]);
126 }
127 G_free(statistics->band_histo);
128 G_free(statistics->band_product);
129}
130
131/*!
132 \brief Calculate statistics for all training areas.
133
134 \param statistics pointer to statistics structure
135 \param perimeters list of all area perimeters
136 \param band_buffer buffer to read band rows into
137 \param band_fd band files descriptors
138
139 \return 1 on success
140 \return 0 on failure
141 */
144 int *band_fd)
145{
146 int i, b, b2, nbands;
147
149
150 G_debug(5, "make_all_statistics()");
151
152 nbands = statistics->nbands;
153 for (b = 0; b < nbands; b++) {
154 statistics->band_sum[b] = 0.0;
155 statistics->band_min[b] = MAX_CATS;
156 statistics->band_max[b] = 0;
157 for (b2 = 0; b2 < nbands; b2++)
158 statistics->band_product[b][b2] = 0.0;
159 for (b2 = 0; b2 < MAX_CATS; b2++)
160 statistics->band_histo[b][b2] = 0;
161 }
162
163 for (i = 0; i < perimeters->nperimeters; i++) {
164 if (!make_statistics(statistics, &perimeters->perimeters[i],
166 return 0;
167 }
168 }
169 for (b = 0; b < statistics->nbands; b++) {
172
173 statistics->band_stddev[b] = stddev_value;
174 statistics->band_mean[b] = mean_value;
175
177 }
178
179 return 1;
180}
181
182/*!
183 \brief Calculate statistics for one training area.
184
185 \param[out] statistics pointer to statistics structure
186 \param perimeter area perimeter
187 \param band_buffer buffer to read band rows into
188 \param band_fd band files descriptors
189
190 \return 1 on success
191 \return 0 on failure
192 */
194 CELL **band_buffer, int *band_fd)
195{
196 int b, b2;
197
198 int value;
199
200 int i;
201
202 int x0, x1;
203
204 int x, y;
205
206 int ncells;
207
208 int nbands;
209
210 G_debug(5, "make_statistics()");
211
212 nbands = statistics->nbands;
213
214 if (perimeter->npoints % 2) {
215 G_warning(_("prepare_signature: outline has odd number of points."));
216 return 0;
217 }
218
219 ncells = 0;
220
221 for (i = 1; i < perimeter->npoints; i += 2) {
222 y = perimeter->points[i].y;
223 if (y != perimeter->points[i - 1].y) {
224 G_warning(
225 _("prepare_signature: scan line %d has odd number of points."),
226 (i + 1) / 2);
227 return 0;
228 }
229 read_band_row(band_buffer, band_fd, nbands, y);
230
231 x0 = perimeter->points[i - 1].x - 1;
232 x1 = perimeter->points[i].x - 1;
233
234 if (x0 > x1) {
235 G_warning(_("signature: perimeter points out of order."));
236 return 0;
237 }
238
239 for (x = x0; x <= x1; x++) {
240 ncells++; /* count interior points */
241 for (b = 0; b < nbands; b++) {
242 value = band_buffer[b][x];
243 G_debug(5,
244 "make_statistics() band: %d, read value: %d (max: %d)",
245 b, value, MAX_CATS);
247 G_warning(_("Data error preparing signatures: value (%d) > "
248 "num of cats (%d)"),
249 value, MAX_CATS);
250 return 0;
251 }
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;
258 G_debug(5, "make_statistics() statistics->band_max[%d]: %d",
259 b, statistics->band_max[b]);
260 }
261
262 for (b2 = 0; b2 <= b; b2++) /* products for variance */
263 statistics->band_product[b][b2] +=
264 value * band_buffer[b2][x];
265 }
266 }
267 }
268 statistics->ncells += ncells;
269
270 return 1;
271}
272
273/*!
274 \brief Create raster map based on statistics.
275
276 \param statistics pointer to statistics structure
277 \param band_buffer buffer to read band rows into
278 \param band_fd band files descriptors
279 \param raster_name name of new raster map
280 */
282 int *band_fd, const char *raster_name)
283{
284 int fd;
285
286 CELL *buffer;
287
288 int n;
289
290 int col;
291
292 int nbands;
293
294 int row, nrows, ncols;
295
296 struct Colors raster_colors;
297
298 int r, g, b;
299
300 int cell_in_ranges;
301
302 nbands = statistics->nbands;
303
304 /* build new raster based on current signature and Nstd */
305
307 buffer = Rast_allocate_c_buf();
308 nrows = Rast_window_rows();
309 ncols = Rast_window_cols();
310
311 for (row = 0; row < nrows; row++) {
312 read_band_row(band_buffer, band_fd, nbands, row);
313 for (col = 0; col < ncols; col++) {
314 buffer[col] = (CELL)0;
315 cell_in_ranges = 1;
316 for (n = 0; n < nbands; n++) {
317 if (band_buffer[n][col] < statistics->band_range_min[n] ||
318 band_buffer[n][col] > statistics->band_range_max[n]) {
319 /* out of at least 1 range */
320 cell_in_ranges = 0;
321 }
322 }
323 if (cell_in_ranges) {
324 /* if in range do the assignment */
325 buffer[col] = (CELL)1;
326 }
327 }
328 Rast_put_row(fd, buffer, CELL_TYPE);
329 }
330 Rast_close(fd);
331
332 /* generate and write the color table for the mask */
334 G_str_to_color(statistics->color, &r, &g, &b);
337}
338
339/* helpers */
340/*!
341 \brief Helper function for computing min and max range in one band.
342
343 Computing min and max range value (distance from mean
344 dependent on number od std ddevs).
345
346 \param statistics pointer to statistics structure
347 \param band band index
348 */
350{
351 float dist;
352
353 dist = statistics->nstd * statistics->band_stddev[band];
354 statistics->band_range_min[band] = statistics->band_mean[band] - dist + 0.5;
355 statistics->band_range_max[band] = statistics->band_mean[band] + dist + 0.5;
356}
357
358/*!
359 \brief Helper function for computing mean.
360
361 Computing mean value of cell category values
362 in one band within training area.
363
364 \param statistics pointer to statistics structure
365 \param band band index
366
367 \return mean value
368 */
370{
371 return statistics->band_sum[band] / statistics->ncells;
372}
373
374/*!
375 \brief Helper function for standard deviation.
376
377 Computing standard deviation of cell category values
378 in one band within training area.
379
380 \param statistics pointer to statistics structure
381 \param band band index
382
383 \return standard deviation
384 */
386{
387 return sqrt(var(statistics, band, band));
388}
389
390/*!
391 \brief Helper function for computing variance.
392
393 Computing variance of cell category values
394 in one band within training area.
395
396 \param statistics pointer to statistics structure
397 \param band1 band index
398 \param band2 band index
399
400 \return variance
401
402 \see var_signature
403 */
405{
406 float product;
407
408 float mean1, mean2;
409
410 int n;
411
412 product = statistics->band_product[band1][band2];
415 n = statistics->ncells;
416
417 return product / n - mean1 * mean2;
418}
419
420/*!
421 \brief Helper function for computing variance for signature file.
422
423 Computing variance of cell category values
424 in one band within training area. Variance is computed
425 in special way.
426
427 \param statistics pointer to statistics structure
428 \param band1 band index
429 \param band2 band index
430
431 \return variance
432
433 \see var
434
435 \todo verify the computation
436 */
438{
439 float product;
440
441 float sum1, sum2;
442
443 int n;
444
445 product = statistics->band_product[band1][band2];
446 sum1 = statistics->band_sum[band1];
447 sum2 = statistics->band_sum[band2];
448 n = statistics->ncells;
449
450 return (product - sum1 * sum2 / n) / (n - 1);
451}
452
453/* getters */
454/*!
455 \brief Get number of bands.
456
457 \param statistics pointer to statistics structure
458 \param[out] nbands number of bands
459 */
461{
462 *nbands = statistics->nbands;
463}
464
465/*!
466 \brief Get category (class).
467
468 \param statistics pointer to statistics structure
469 \param[out] cat category
470 */
472{
473 *cat = statistics->cat;
474}
475
476/*!
477 \brief Get category (class) name.
478
479 \note \a name is pointer to already allocated
480 const char * in \a statistics.
481 You should not free it.
482
483 \param statistics pointer to statistics structure
484 \param[out] name category name
485 */
491
492/*!
493 \brief Get category (class) color.
494
495 \note \a color is pointer to already allocated
496 const char * in \a statistics.
497 You should not free it.
498
499 \param statistics pointer to statistics structure
500 \param[out] color category color
501 */
503 const char **color)
504{
505 *color = statistics->color;
506}
507
508/*!
509 \brief Get number of cells in training areas.
510
511 \param statistics pointer to statistics structure
512 \param[out] ncells number of cells
513 */
515{
516 *ncells = statistics->ncells;
517}
518
519/*!
520 \brief Get the multiplier of standard deviation.
521
522 \param statistics pointer to statistics structure
523 \param[out] nstd multiplier of standard deviation
524 */
526{
527 *nstd = statistics->nstd;
528}
529
530/*!
531 \brief Set the multiplier of standard deviation.
532
533 \param statistics pointer to statistics structure
534 \param nstd multiplier of standard deviation
535 */
537{
538 statistics->nstd = nstd;
539}
540
541/*!
542 \brief Get minimum value in band.
543
544 \param statistics pointer to statistics structure
545 \param band band index
546 \param[out] min minimum value
547
548 \return 1 on success
549 \return 0 band index out of range
550 */
552 int *min)
553{
554 if (band >= statistics->nbands) {
555 G_warning(_("Band index out of range"));
556 return 0;
557 }
558
559 *min = statistics->band_min[band];
560
561 return 1;
562}
563
564/*!
565 \brief Get maximum value in band.
566
567 \param statistics pointer to statistics structure
568 \param band band index
569 \param[out] max maximum value
570
571 \return 1 on success
572 \return 0 band index out of range
573 */
575 int *max)
576{
577 if (band >= statistics->nbands) {
578 G_warning(_("Band index out of range"));
579 return 0;
580 }
581
582 *max = statistics->band_max[band];
583
584 return 1;
585}
586
587/*!
588 \brief Get sum of values in band.
589
590 \param statistics pointer to statistics structure
591 \param band band index
592 \param[out] sum sum
593
594 \return 1 on success
595 \return 0 band index out of range
596 */
598 float *sum)
599{
600 if (band >= statistics->nbands) {
601 G_warning(_("Band index out of range"));
602 return 0;
603 }
604
605 *sum = statistics->band_sum[band];
606
607 return 1;
608}
609
610/*!
611 \brief Get mean of cell category values in band.
612
613 \param statistics pointer to statistics structure
614 \param band band index
615 \param[out] mean mean
616
617 \return 1 on success
618 \return 0 band index out of range
619 */
621 float *mean)
622{
623 if (band >= statistics->nbands) {
624 G_warning(_("Band index out of range"));
625 return 0;
626 }
627
628 *mean = statistics->band_mean[band];
629
630 return 1;
631}
632
633/*!
634 \brief Get standard deviation of cell category values in band.
635
636 \param statistics pointer to statistics structure
637 \param band band index
638 \param[out] stddev standard deviation
639
640 \return 1 on success
641 \return 0 band index out of range
642 */
644 float *stddev)
645{
646 if (band >= statistics->nbands) {
647 G_warning(_("Band index out of range"));
648 return 0;
649 }
650
651 *stddev = statistics->band_stddev[band];
652
653 return 1;
654}
655
656/*!
657 \brief Get histogram value in band.
658
659 Each band has one value for each raster cell category.
660 Value is number of cells in category.
661
662 \param statistics pointer to statistics structure
663 \param band band index
664 \param cat raster cell category
665 \param[out] value number of cells in category
666
667 \return 1 on success
668 \return 0 band index or cell category value out of range
669 */
671 int cat, int *value)
672{
673 if (band >= statistics->nbands) {
674 G_warning(_("Band index out of range"));
675 return 0;
676 }
677 if (cat >= MAX_CATS) {
678 G_warning(_("Cell category value out of range"));
679 return 0;
680 }
681
682 *value = statistics->band_histo[band][cat];
683
684 return 1;
685}
686
687/*!
688 \brief Get product value
689
690 Product value of two bands is sum of products
691 of cell category values of two bands.
692 Only cells from training areas are taken into account.
693
694 \param statistics statistics object
695 \param band1 index of first band
696 \param band2 index of second band
697 \param[out] value product value
698
699 \return 1 on success
700 \return 0 band index out of range
701 */
703 int band2, float *value)
704{
705 if (band1 >= statistics->nbands || band2 >= statistics->nbands) {
706 G_warning(_("Band index out of range"));
707 return 0;
708 }
709
710 *value = statistics->band_product[band1][band2];
711
712 return 1;
713}
714
715/*!
716 \brief Get minimum cell value based on mean and standard deviation for band.
717
718 \param statistics pointer to statistics structure
719 \param band band index
720 \param[out] min minimum value
721
722 \return 1 on success
723 \return 0 band index out of range
724 */
726 int *min)
727{
728 if (band >= statistics->nbands) {
729 G_warning(_("Band index out of range"));
730 return 0;
731 }
732
733 *min = statistics->band_range_min[band];
734
735 return 1;
736}
737
738/*!
739 \brief Get maximum cell value based on mean and standard deviation for band.
740
741 \param statistics pointer to statistics structure
742 \param band band index
743 \param[out] max maximum value
744
745 \return 1 on success
746 \return 0 band index out of range
747 */
749 int *max)
750{
751 if (band >= statistics->nbands) {
752 G_warning(_("Band index out of range"));
753 return 0;
754 }
755
756 *max = statistics->band_range_max[band];
757
758 return 1;
759}
#define NULL
Definition ccmath.h:32
AMI_err name(char **stream_name)
Definition ami_stream.h:426
int G_str_to_color(const char *, int *, int *, int *)
Parse color string and set red,green,blue.
Definition color_str.c:103
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_calloc(m, n)
Definition defs/gis.h:140
void G_warning(const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:33
CELL * Rast_allocate_c_buf(void)
Allocate memory for a CELL type raster map.
Definition alloc_cell.c:80
void Rast_set_c_color(CELL, int, int, int, struct Colors *)
Set a category color (CELL)
Definition color_set.c:41
void Rast_close(int)
Close a raster map.
void Rast_init_colors(struct Colors *)
Initialize color structure.
Definition color_init.c:25
int Rast_window_cols(void)
Number of columns in active window.
void Rast_put_row(int, const void *, RASTER_MAP_TYPE)
Writes the next row for cell/fcell/dcell file.
int Rast_window_rows(void)
Number of rows in active window.
int Rast_open_c_new(const char *)
Opens a new cell file in a database (compressed)
void Rast_write_colors(const char *, const char *, struct Colors *)
Write map layer color table.
#define min(x, y)
Definition draw2.c:29
#define max(x, y)
Definition draw2.c:30
int CELL
Definition gis.h:634
#define _(str)
Definition glocale.h:10
void read_band_row(CELL **band_buffer, int *band_fd, int nbands, int row)
Read one row of each band.
void I_iclass_statistics_set_nstd(IClass_statistics *statistics, float nstd)
Set the multiplier of standard deviation.
int I_iclass_statistics_get_histo(IClass_statistics *statistics, int band, int cat, int *value)
Get histogram value in band.
void I_iclass_statistics_get_nstd(IClass_statistics *statistics, float *nstd)
Get the multiplier of standard deviation.
void alloc_statistics(IClass_statistics *statistics, int nbands)
Allocate space for statistics.
int I_iclass_statistics_get_sum(IClass_statistics *statistics, int band, float *sum)
Get sum of values in band.
int I_iclass_statistics_get_range_min(IClass_statistics *statistics, int band, int *min)
Get minimum cell value based on mean and standard deviation for band.
int I_iclass_statistics_get_mean(IClass_statistics *statistics, int band, float *mean)
Get mean of cell category values in band.
void band_range(IClass_statistics *statistics, int band)
Helper function for computing min and max range in one band.
int I_iclass_statistics_get_max(IClass_statistics *statistics, int band, int *max)
Get maximum value in band.
float mean(IClass_statistics *statistics, int band)
Helper function for computing mean.
void I_iclass_init_statistics(IClass_statistics *statistics, int category, const char *name, const char *color, float nstd)
Initialize statistics.
float stddev(IClass_statistics *statistics, int band)
Helper function for standard deviation.
void create_raster(IClass_statistics *statistics, CELL **band_buffer, int *band_fd, const char *raster_name)
Create raster map based on statistics.
int I_iclass_statistics_get_product(IClass_statistics *statistics, int band1, int band2, float *value)
Get product value.
float var_signature(IClass_statistics *statistics, int band1, int band2)
Helper function for computing variance for signature file.
float var(IClass_statistics *statistics, int band1, int band2)
Helper function for computing variance.
void I_iclass_statistics_get_nbands(IClass_statistics *statistics, int *nbands)
Get number of bands.
int I_iclass_statistics_get_range_max(IClass_statistics *statistics, int band, int *max)
Get maximum cell value based on mean and standard deviation for band.
void I_iclass_free_statistics(IClass_statistics *statistics)
Free space allocated for statistics attributes.
int I_iclass_statistics_get_min(IClass_statistics *statistics, int band, int *min)
Get minimum value in band.
int make_all_statistics(IClass_statistics *statistics, IClass_perimeter_list *perimeters, CELL **band_buffer, int *band_fd)
Calculate statistics for all training areas.
void I_iclass_statistics_get_ncells(IClass_statistics *statistics, int *ncells)
Get number of cells in training areas.
void I_iclass_statistics_get_cat(IClass_statistics *statistics, int *cat)
Get category (class).
void I_iclass_statistics_get_name(IClass_statistics *statistics, const char **name)
Get category (class) name.
int I_iclass_statistics_get_stddev(IClass_statistics *statistics, int band, float *stddev)
Get standard deviation of cell category values in band.
void I_iclass_statistics_get_color(IClass_statistics *statistics, const char **color)
Get category (class) color.
int make_statistics(IClass_statistics *statistics, IClass_perimeter *perimeter, CELL **band_buffer, int *band_fd)
Calculate statistics for one training area.
float g
Definition named_colr.c:7
const char * name
Definition named_colr.c:6
double b
Definition r_raster.c:39
double r
Definition r_raster.c:39
#define CELL_TYPE
Definition raster.h:11
Definition gis.h:692
#define x