GRASS 8 Programmer's Manual 8.6.0dev(2026)-d2adb3a889
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 SPDX-FileCopyrightText: 1999-2007, 2011 GRASS Development Team
13 SPDX-License-Identifier: GPL-2.0-or-later
14
15 \author David Satnik, Central Washington University (original author)
16 \author Markus Neteler <neteler itc.it> (i.class module)
17 \author Bernhard Reiter <bernhard intevation.de> (i.class module)
18 \author Brad Douglas <rez touchofmadness.com>(i.class module)
19 \author Glynn Clements <glynn gclements.plus.com> (i.class module)
20 \author Hamish Bowman <hamish_b yahoo.com> (i.class module)
21 \author Jan-Oliver Wagner <jan intevation.de> (i.class module)
22 \author Anna Kratochvilova <kratochanna gmail.com> (rewriting for wx.iclass)
23 \author Vaclav Petras <wenzeslaus gmail.com> (rewriting for wx.iclass)
24 */
25
26#include <math.h>
27
28#include <grass/imagery.h>
29#include <grass/glocale.h>
30#include <grass/colors.h>
31
32#include "iclass_local_proto.h"
33
34/*!
35 \brief Initialize statistics.
36
37 \param[out] statistics pointer to statistics structure
38 \param category category (class)
39 \param name class name
40 \param color class color
41 \param nstd standard deviation
42 */
44 const char *name, const char *color, float nstd)
45{
46 G_debug(4, "init_statistics() category=%d, name=%s, color=%s, nstd=%f",
47 category, name, color, nstd);
48
49 statistics->cat = category;
51 statistics->color = G_store(color);
52 statistics->nstd = nstd;
53
54 statistics->ncells = 0;
55 statistics->nbands = 0;
56
57 statistics->band_min = NULL;
58 statistics->band_max = NULL;
59 statistics->band_sum = NULL;
60 statistics->band_mean = NULL;
61 statistics->band_stddev = NULL;
62 statistics->band_product = NULL;
63 statistics->band_histo = NULL;
64 statistics->band_range_min = NULL;
65 statistics->band_range_max = NULL;
66}
67
68/*!
69 \brief Allocate space for statistics.
70
71 \param statistics pointer to statistics structure
72 \param nbands number of band files
73 */
75{
76 int i;
77
78 G_debug(4, "alloc_statistics()");
79
80 statistics->nbands = nbands;
81
82 statistics->band_min = (int *)G_calloc(nbands, sizeof(int));
83 statistics->band_max = (int *)G_calloc(nbands, sizeof(int));
84 statistics->band_sum = (float *)G_calloc(nbands, sizeof(float));
85 statistics->band_mean = (float *)G_calloc(nbands, sizeof(float));
86 statistics->band_stddev = (float *)G_calloc(nbands, sizeof(float));
87 statistics->band_product = (float **)G_calloc(nbands, sizeof(float *));
88 statistics->band_histo = (int **)G_calloc(nbands, sizeof(int *));
89 statistics->band_range_min = (int *)G_calloc(nbands, sizeof(int));
90 statistics->band_range_max = (int *)G_calloc(nbands, sizeof(int));
91
92 for (i = 0; i < nbands; i++) {
93 statistics->band_product[i] = (float *)G_calloc(nbands, sizeof(float));
94 statistics->band_histo[i] = (int *)G_calloc(MAX_CATS, sizeof(int));
95 }
96}
97
98/*!
99 \brief Free space allocated for statistics attributes.
100
101 Frees all allocated arrays in statistics structure.
102
103 \param statistics pointer to statistics structure
104 */
106{
107 int i;
108
109 G_debug(4, "free_statistics()");
110
111 G_free((char *)statistics->name);
112 G_free((char *)statistics->color);
113 G_free(statistics->band_min);
114 G_free(statistics->band_max);
115 G_free(statistics->band_sum);
116 G_free(statistics->band_mean);
117 G_free(statistics->band_stddev);
118 G_free(statistics->band_range_max);
119 G_free(statistics->band_range_min);
120
121 for (i = 0; i < statistics->nbands; i++) {
122 G_free(statistics->band_histo[i]);
123 G_free(statistics->band_product[i]);
124 }
125 G_free(statistics->band_histo);
126 G_free(statistics->band_product);
127}
128
129/*!
130 \brief Calculate statistics for all training areas.
131
132 \param statistics pointer to statistics structure
133 \param perimeters list of all area perimeters
134 \param band_buffer buffer to read band rows into
135 \param band_fd band files descriptors
136
137 \return 1 on success
138 \return 0 on failure
139 */
142 int *band_fd)
143{
144 int i, b, b2, nbands;
145
147
148 G_debug(5, "make_all_statistics()");
149
150 nbands = statistics->nbands;
151 for (b = 0; b < nbands; b++) {
152 statistics->band_sum[b] = 0.0;
153 statistics->band_min[b] = MAX_CATS;
154 statistics->band_max[b] = 0;
155 for (b2 = 0; b2 < nbands; b2++)
156 statistics->band_product[b][b2] = 0.0;
157 for (b2 = 0; b2 < MAX_CATS; b2++)
158 statistics->band_histo[b][b2] = 0;
159 }
160
161 for (i = 0; i < perimeters->nperimeters; i++) {
162 if (!make_statistics(statistics, &perimeters->perimeters[i],
164 return 0;
165 }
166 }
167 for (b = 0; b < statistics->nbands; b++) {
170
171 statistics->band_stddev[b] = stddev_value;
172 statistics->band_mean[b] = mean_value;
173
175 }
176
177 return 1;
178}
179
180/*!
181 \brief Calculate statistics for one training area.
182
183 \param[out] statistics pointer to statistics structure
184 \param perimeter area perimeter
185 \param band_buffer buffer to read band rows into
186 \param band_fd band files descriptors
187
188 \return 1 on success
189 \return 0 on failure
190 */
192 CELL **band_buffer, int *band_fd)
193{
194 int b, b2;
195
196 int value;
197
198 int i;
199
200 int x0, x1;
201
202 int x, y;
203
204 int ncells;
205
206 int nbands;
207
208 G_debug(5, "make_statistics()");
209
210 nbands = statistics->nbands;
211
212 if (perimeter->npoints % 2) {
213 G_warning(_("prepare_signature: outline has odd number of points."));
214 return 0;
215 }
216
217 ncells = 0;
218
219 for (i = 1; i < perimeter->npoints; i += 2) {
220 y = perimeter->points[i].y;
221 if (y != perimeter->points[i - 1].y) {
222 G_warning(
223 _("prepare_signature: scan line %d has odd number of points."),
224 (i + 1) / 2);
225 return 0;
226 }
227 read_band_row(band_buffer, band_fd, nbands, y);
228
229 x0 = perimeter->points[i - 1].x - 1;
230 x1 = perimeter->points[i].x - 1;
231
232 if (x0 > x1) {
233 G_warning(_("signature: perimeter points out of order."));
234 return 0;
235 }
236
237 for (x = x0; x <= x1; x++) {
238 ncells++; /* count interior points */
239 for (b = 0; b < nbands; b++) {
240 value = band_buffer[b][x];
241 G_debug(5,
242 "make_statistics() band: %d, read value: %d (max: %d)",
243 b, value, MAX_CATS);
245 G_warning(_("Data error preparing signatures: value (%d) > "
246 "num of cats (%d)"),
247 value, MAX_CATS);
248 return 0;
249 }
250 statistics->band_sum[b] += value; /* sum for means */
251 statistics->band_histo[b][value]++; /* histogram */
252 if (statistics->band_min[b] > value)
253 statistics->band_min[b] = value; /* absolute min, max */
254 if (statistics->band_max[b] < value) {
255 statistics->band_max[b] = value;
256 G_debug(5, "make_statistics() statistics->band_max[%d]: %d",
257 b, statistics->band_max[b]);
258 }
259
260 for (b2 = 0; b2 <= b; b2++) /* products for variance */
261 statistics->band_product[b][b2] +=
262 value * band_buffer[b2][x];
263 }
264 }
265 }
266 statistics->ncells += ncells;
267
268 return 1;
269}
270
271/*!
272 \brief Create raster map based on statistics.
273
274 \param statistics pointer to statistics structure
275 \param band_buffer buffer to read band rows into
276 \param band_fd band files descriptors
277 \param raster_name name of new raster map
278 */
280 int *band_fd, const char *raster_name)
281{
282 int fd;
283
284 CELL *buffer;
285
286 int n;
287
288 int col;
289
290 int nbands;
291
292 int row, nrows, ncols;
293
294 struct Colors raster_colors;
295
296 int r, g, b;
297
298 int cell_in_ranges;
299
300 nbands = statistics->nbands;
301
302 /* build new raster based on current signature and Nstd */
303
305 buffer = Rast_allocate_c_buf();
306 nrows = Rast_window_rows();
307 ncols = Rast_window_cols();
308
309 for (row = 0; row < nrows; row++) {
310 read_band_row(band_buffer, band_fd, nbands, row);
311 for (col = 0; col < ncols; col++) {
312 buffer[col] = (CELL)0;
313 cell_in_ranges = 1;
314 for (n = 0; n < nbands; n++) {
315 if (band_buffer[n][col] < statistics->band_range_min[n] ||
316 band_buffer[n][col] > statistics->band_range_max[n]) {
317 /* out of at least 1 range */
318 cell_in_ranges = 0;
319 }
320 }
321 if (cell_in_ranges) {
322 /* if in range do the assignment */
323 buffer[col] = (CELL)1;
324 }
325 }
326 Rast_put_row(fd, buffer, CELL_TYPE);
327 }
328 Rast_close(fd);
329
330 /* generate and write the color table for the mask */
332 G_str_to_color(statistics->color, &r, &g, &b);
335}
336
337/* helpers */
338/*!
339 \brief Helper function for computing min and max range in one band.
340
341 Computing min and max range value (distance from mean
342 dependent on number od std ddevs).
343
344 \param statistics pointer to statistics structure
345 \param band band index
346 */
348{
349 float dist;
350
351 dist = statistics->nstd * statistics->band_stddev[band];
352 statistics->band_range_min[band] = statistics->band_mean[band] - dist + 0.5;
353 statistics->band_range_max[band] = statistics->band_mean[band] + dist + 0.5;
354}
355
356/*!
357 \brief Helper function for computing mean.
358
359 Computing mean value of cell category values
360 in one band within training area.
361
362 \param statistics pointer to statistics structure
363 \param band band index
364
365 \return mean value
366 */
368{
369 return statistics->band_sum[band] / statistics->ncells;
370}
371
372/*!
373 \brief Helper function for standard deviation.
374
375 Computing standard deviation of cell category values
376 in one band within training area.
377
378 \param statistics pointer to statistics structure
379 \param band band index
380
381 \return standard deviation
382 */
384{
385 return sqrt(var(statistics, band, band));
386}
387
388/*!
389 \brief Helper function for computing variance.
390
391 Computing variance of cell category values
392 in one band within training area.
393
394 \param statistics pointer to statistics structure
395 \param band1 band index
396 \param band2 band index
397
398 \return variance
399
400 \see var_signature
401 */
403{
404 float product;
405
406 float mean1, mean2;
407
408 int n;
409
410 product = statistics->band_product[band1][band2];
413 n = statistics->ncells;
414
415 return product / n - mean1 * mean2;
416}
417
418/*!
419 \brief Helper function for computing variance for signature file.
420
421 Computing variance of cell category values
422 in one band within training area. Variance is computed
423 in special way.
424
425 \param statistics pointer to statistics structure
426 \param band1 band index
427 \param band2 band index
428
429 \return variance
430
431 \see var
432
433 \todo verify the computation
434 */
436{
437 float product;
438
439 float sum1, sum2;
440
441 int n;
442
443 product = statistics->band_product[band1][band2];
444 sum1 = statistics->band_sum[band1];
445 sum2 = statistics->band_sum[band2];
446 n = statistics->ncells;
447
448 return (product - sum1 * sum2 / n) / (n - 1);
449}
450
451/* getters */
452/*!
453 \brief Get number of bands.
454
455 \param statistics pointer to statistics structure
456 \param[out] nbands number of bands
457 */
459{
460 *nbands = statistics->nbands;
461}
462
463/*!
464 \brief Get category (class).
465
466 \param statistics pointer to statistics structure
467 \param[out] cat category
468 */
470{
471 *cat = statistics->cat;
472}
473
474/*!
475 \brief Get category (class) name.
476
477 \note \a name is pointer to already allocated
478 const char * in \a statistics.
479 You should not free it.
480
481 \param statistics pointer to statistics structure
482 \param[out] name category name
483 */
489
490/*!
491 \brief Get category (class) color.
492
493 \note \a color is pointer to already allocated
494 const char * in \a statistics.
495 You should not free it.
496
497 \param statistics pointer to statistics structure
498 \param[out] color category color
499 */
501 const char **color)
502{
503 *color = statistics->color;
504}
505
506/*!
507 \brief Get number of cells in training areas.
508
509 \param statistics pointer to statistics structure
510 \param[out] ncells number of cells
511 */
513{
514 *ncells = statistics->ncells;
515}
516
517/*!
518 \brief Get the multiplier of standard deviation.
519
520 \param statistics pointer to statistics structure
521 \param[out] nstd multiplier of standard deviation
522 */
524{
525 *nstd = statistics->nstd;
526}
527
528/*!
529 \brief Set the multiplier of standard deviation.
530
531 \param statistics pointer to statistics structure
532 \param nstd multiplier of standard deviation
533 */
535{
536 statistics->nstd = nstd;
537}
538
539/*!
540 \brief Get minimum value in band.
541
542 \param statistics pointer to statistics structure
543 \param band band index
544 \param[out] min minimum value
545
546 \return 1 on success
547 \return 0 band index out of range
548 */
550 int *min)
551{
552 if (band >= statistics->nbands) {
553 G_warning(_("Band index out of range"));
554 return 0;
555 }
556
557 *min = statistics->band_min[band];
558
559 return 1;
560}
561
562/*!
563 \brief Get maximum value in band.
564
565 \param statistics pointer to statistics structure
566 \param band band index
567 \param[out] max maximum value
568
569 \return 1 on success
570 \return 0 band index out of range
571 */
573 int *max)
574{
575 if (band >= statistics->nbands) {
576 G_warning(_("Band index out of range"));
577 return 0;
578 }
579
580 *max = statistics->band_max[band];
581
582 return 1;
583}
584
585/*!
586 \brief Get sum of values in band.
587
588 \param statistics pointer to statistics structure
589 \param band band index
590 \param[out] sum sum
591
592 \return 1 on success
593 \return 0 band index out of range
594 */
596 float *sum)
597{
598 if (band >= statistics->nbands) {
599 G_warning(_("Band index out of range"));
600 return 0;
601 }
602
603 *sum = statistics->band_sum[band];
604
605 return 1;
606}
607
608/*!
609 \brief Get mean of cell category values in band.
610
611 \param statistics pointer to statistics structure
612 \param band band index
613 \param[out] mean mean
614
615 \return 1 on success
616 \return 0 band index out of range
617 */
619 float *mean)
620{
621 if (band >= statistics->nbands) {
622 G_warning(_("Band index out of range"));
623 return 0;
624 }
625
626 *mean = statistics->band_mean[band];
627
628 return 1;
629}
630
631/*!
632 \brief Get standard deviation of cell category values in band.
633
634 \param statistics pointer to statistics structure
635 \param band band index
636 \param[out] stddev standard deviation
637
638 \return 1 on success
639 \return 0 band index out of range
640 */
642 float *stddev)
643{
644 if (band >= statistics->nbands) {
645 G_warning(_("Band index out of range"));
646 return 0;
647 }
648
649 *stddev = statistics->band_stddev[band];
650
651 return 1;
652}
653
654/*!
655 \brief Get histogram value in band.
656
657 Each band has one value for each raster cell category.
658 Value is number of cells in category.
659
660 \param statistics pointer to statistics structure
661 \param band band index
662 \param cat raster cell category
663 \param[out] value number of cells in category
664
665 \return 1 on success
666 \return 0 band index or cell category value out of range
667 */
669 int cat, int *value)
670{
671 if (band >= statistics->nbands) {
672 G_warning(_("Band index out of range"));
673 return 0;
674 }
675 if (cat >= MAX_CATS) {
676 G_warning(_("Cell category value out of range"));
677 return 0;
678 }
679
680 *value = statistics->band_histo[band][cat];
681
682 return 1;
683}
684
685/*!
686 \brief Get product value
687
688 Product value of two bands is sum of products
689 of cell category values of two bands.
690 Only cells from training areas are taken into account.
691
692 \param statistics statistics object
693 \param band1 index of first band
694 \param band2 index of second band
695 \param[out] value product value
696
697 \return 1 on success
698 \return 0 band index out of range
699 */
701 int band2, float *value)
702{
703 if (band1 >= statistics->nbands || band2 >= statistics->nbands) {
704 G_warning(_("Band index out of range"));
705 return 0;
706 }
707
708 *value = statistics->band_product[band1][band2];
709
710 return 1;
711}
712
713/*!
714 \brief Get minimum cell value based on mean and standard deviation for band.
715
716 \param statistics pointer to statistics structure
717 \param band band index
718 \param[out] min minimum value
719
720 \return 1 on success
721 \return 0 band index out of range
722 */
724 int *min)
725{
726 if (band >= statistics->nbands) {
727 G_warning(_("Band index out of range"));
728 return 0;
729 }
730
731 *min = statistics->band_range_min[band];
732
733 return 1;
734}
735
736/*!
737 \brief Get maximum cell value based on mean and standard deviation for band.
738
739 \param statistics pointer to statistics structure
740 \param band band index
741 \param[out] max maximum value
742
743 \return 1 on success
744 \return 0 band index out of range
745 */
747 int *max)
748{
749 if (band >= statistics->nbands) {
750 G_warning(_("Band index out of range"));
751 return 0;
752 }
753
754 *max = statistics->band_range_max[band];
755
756 return 1;
757}
#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:99
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_calloc(m, n)
Definition defs/gis.h:137
void G_warning(const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:31
CELL * Rast_allocate_c_buf(void)
Allocate memory for a CELL type raster map.
Definition alloc_cell.c:78
void Rast_set_c_color(CELL, int, int, int, struct Colors *)
Set a category color (CELL)
Definition color_set.c:39
void Rast_close(int)
Close a raster map.
void Rast_init_colors(struct Colors *)
Initialize color structure.
Definition color_init.c:23
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:631
#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:37
double r
Definition r_raster.c:37
#define CELL_TYPE
Definition raster.h:11
Definition gis.h:689
#define x