iclass_statistics.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /*!
  2. \file lib/imagery/iclass_statistics.c
  3. \brief Imagery library - functions for wx.iclass
  4. Computation based on training areas for supervised classification.
  5. Based on i.class module (GRASS 6).
  6. Computing statistical values (mean, min, max, ...) from given area
  7. perimeters for each band.
  8. Copyright (C) 1999-2007, 2011 by the GRASS Development Team
  9. This program is free software under the GNU General Public License
  10. (>=v2). Read the file COPYING that comes with GRASS for details.
  11. \author David Satnik, Central Washington University (original author)
  12. \author Markus Neteler <neteler itc.it> (i.class module)
  13. \author Bernhard Reiter <bernhard intevation.de> (i.class module)
  14. \author Brad Douglas <rez touchofmadness.com>(i.class module)
  15. \author Glynn Clements <glynn gclements.plus.com> (i.class module)
  16. \author Hamish Bowman <hamish_b yahoo.com> (i.class module)
  17. \author Jan-Oliver Wagner <jan intevation.de> (i.class module)
  18. \author Anna Kratochvilova <kratochanna gmail.com> (rewriting for wx.iclass)
  19. \author Vaclav Petras <wenzeslaus gmail.com> (rewriting for wx.iclass)
  20. */
  21. #include <math.h>
  22. #include <grass/imagery.h>
  23. #include <grass/glocale.h>
  24. #include <grass/colors.h>
  25. #include "iclass_local_proto.h"
  26. /*!
  27. \brief Initialize statistics.
  28. \param[out] statistics pointer to statistics structure
  29. \param category category (class)
  30. \param name class name
  31. \param color class color
  32. \param nstd standard deviation
  33. */
  34. void I_iclass_init_statistics(IClass_statistics * statistics, int category,
  35. const char *name, const char *color, float nstd)
  36. {
  37. G_debug(4, "init_statistics() category=%d, name=%s, color=%s, nstd=%f",
  38. category, name, color, nstd);
  39. statistics->cat = category;
  40. statistics->name = G_store(name);
  41. statistics->color = G_store(color);
  42. statistics->nstd = nstd;
  43. statistics->ncells = 0;
  44. statistics->nbands = 0;
  45. statistics->band_min = NULL;
  46. statistics->band_max = NULL;
  47. statistics->band_sum = NULL;
  48. statistics->band_mean = NULL;
  49. statistics->band_stddev = NULL;
  50. statistics->band_product = NULL;
  51. statistics->band_histo = NULL;
  52. statistics->band_range_min = NULL;
  53. statistics->band_range_max = NULL;
  54. }
  55. /*!
  56. \brief Allocate space for statistics.
  57. \param statistics pointer to statistics structure
  58. \param nbands number of band files
  59. */
  60. void alloc_statistics(IClass_statistics * statistics, int nbands)
  61. {
  62. int i;
  63. G_debug(4, "alloc_statistics()");
  64. statistics->nbands = nbands;
  65. statistics->band_min = (int *)G_calloc(nbands, sizeof(int));
  66. statistics->band_max = (int *)G_calloc(nbands, sizeof(int));
  67. statistics->band_sum = (float *)G_calloc(nbands, sizeof(float));
  68. statistics->band_mean = (float *)G_calloc(nbands, sizeof(float));
  69. statistics->band_stddev = (float *)G_calloc(nbands, sizeof(float));
  70. statistics->band_product = (float **)G_calloc(nbands, sizeof(float *));
  71. statistics->band_histo = (int **)G_calloc(nbands, sizeof(int *));
  72. statistics->band_range_min = (int *)G_calloc(nbands, sizeof(int));
  73. statistics->band_range_max = (int *)G_calloc(nbands, sizeof(int));
  74. for (i = 0; i < nbands; i++) {
  75. statistics->band_product[i] =
  76. (float *)G_calloc(nbands, sizeof(float));
  77. statistics->band_histo[i] = (int *)G_calloc(MAX_CATS, sizeof(int));
  78. }
  79. }
  80. /*!
  81. \brief Free space allocated for statistics attributes.
  82. Frees all allocated arrays in statistics structure.
  83. \param statistics pointer to statistics structure
  84. */
  85. void I_iclass_free_statistics(IClass_statistics * statistics)
  86. {
  87. int i;
  88. G_debug(4, "free_statistics()");
  89. G_free((char *) statistics->name);
  90. G_free((char *) statistics->color);
  91. G_free(statistics->band_min);
  92. G_free(statistics->band_max);
  93. G_free(statistics->band_sum);
  94. G_free(statistics->band_mean);
  95. G_free(statistics->band_stddev);
  96. G_free(statistics->band_range_max);
  97. G_free(statistics->band_range_min);
  98. for (i = 0; i < statistics->nbands; i++) {
  99. G_free(statistics->band_histo[i]);
  100. G_free(statistics->band_product[i]);
  101. }
  102. G_free(statistics->band_histo);
  103. G_free(statistics->band_product);
  104. }
  105. /*!
  106. \brief Calculate statistics for all training areas.
  107. \param statistics pointer to statistics structure
  108. \param perimeters list of all area perimeters
  109. \param band_buffer buffer to read band rows into
  110. \param band_fd band files descriptors
  111. \return 1 on succes
  112. \return 0 on failure
  113. */
  114. int make_all_statistics(IClass_statistics * statistics,
  115. IClass_perimeter_list * perimeters,
  116. CELL ** band_buffer, int *band_fd)
  117. {
  118. int i, b, b2, nbands;
  119. float mean_value, stddev_value;
  120. G_debug(5, "make_all_statistics()");
  121. nbands = statistics->nbands;
  122. for (b = 0; b < nbands; b++) {
  123. statistics->band_sum[b] = 0.0;
  124. statistics->band_min[b] = MAX_CATS;
  125. statistics->band_max[b] = 0;
  126. for (b2 = 0; b2 < nbands; b2++)
  127. statistics->band_product[b][b2] = 0.0;
  128. for (b2 = 0; b2 < MAX_CATS; b2++)
  129. statistics->band_histo[b][b2] = 0;
  130. }
  131. for (i = 0; i < perimeters->nperimeters; i++) {
  132. if (!make_statistics
  133. (statistics, &perimeters->perimeters[i], band_buffer, band_fd)) {
  134. return 0;
  135. }
  136. }
  137. for (b = 0; b < statistics->nbands; b++) {
  138. mean_value = mean(statistics, b);
  139. stddev_value = stddev(statistics, b);
  140. statistics->band_stddev[b] = stddev_value;
  141. statistics->band_mean[b] = mean_value;
  142. band_range(statistics, b);
  143. }
  144. return 1;
  145. }
  146. /*!
  147. \brief Calculate statistics for one training area.
  148. \param[out] statistics pointer to statistics structure
  149. \param perimeter area perimeter
  150. \param band_buffer buffer to read band rows into
  151. \param band_fd band files descriptors
  152. \return 1 on succes
  153. \return 0 on failure
  154. */
  155. int make_statistics(IClass_statistics * statistics,
  156. IClass_perimeter * perimeter, CELL ** band_buffer,
  157. int *band_fd)
  158. {
  159. int b, b2;
  160. int value;
  161. int i;
  162. int x0, x1;
  163. int x, y;
  164. int ncells;
  165. int nbands;
  166. G_debug(5, "make_statistics()");
  167. nbands = statistics->nbands;
  168. if (perimeter->npoints % 2) {
  169. G_warning(_("prepare_signature: outline has odd number of points."));
  170. return 0;
  171. }
  172. ncells = 0;
  173. for (i = 1; i < perimeter->npoints; i += 2) {
  174. y = perimeter->points[i].y;
  175. if (y != perimeter->points[i - 1].y) {
  176. G_warning(_("prepare_signature: scan line %d has odd number of points."),
  177. (i + 1) / 2);
  178. return 0;
  179. }
  180. read_band_row(band_buffer, band_fd, nbands, y);
  181. x0 = perimeter->points[i - 1].x - 1;
  182. x1 = perimeter->points[i].x - 1;
  183. if (x0 > x1) {
  184. G_warning(_("signature: perimeter points out of order."));
  185. return 0;
  186. }
  187. for (x = x0; x <= x1; x++) {
  188. ncells++; /* count interior points */
  189. for (b = 0; b < nbands; b++) {
  190. value = band_buffer[b][x];
  191. G_debug(5, "make_statistics() band: %d, read value: %d (max: %d)",
  192. b, value, MAX_CATS);
  193. if (value < 0 || value > MAX_CATS - 1) {
  194. G_warning(_("Data error preparing signatures: value (%d) > num of cats (%d)"),
  195. value, MAX_CATS);
  196. return 0;
  197. }
  198. statistics->band_sum[b] += value; /* sum for means */
  199. statistics->band_histo[b][value]++; /* histogram */
  200. if (statistics->band_min[b] > value)
  201. statistics->band_min[b] = value; /* absolute min, max */
  202. if (statistics->band_max[b] < value) {
  203. statistics->band_max[b] = value;
  204. G_debug(5,
  205. "make_statistics() statistics->band_max[%d]: %d",
  206. b, statistics->band_max[b]);
  207. }
  208. for (b2 = 0; b2 <= b; b2++) /* products for variance */
  209. statistics->band_product[b][b2] +=
  210. value * band_buffer[b2][x];
  211. }
  212. }
  213. }
  214. statistics->ncells += ncells;
  215. return 1;
  216. }
  217. /*!
  218. \brief Create raster map based on statistics.
  219. \param statistics pointer to statistics structure
  220. \param band_buffer buffer to read band rows into
  221. \param band_fd band files descriptors
  222. \param raster_name name of new raster map
  223. */
  224. void create_raster(IClass_statistics * statistics, CELL ** band_buffer,
  225. int *band_fd, const char *raster_name)
  226. {
  227. int fd;
  228. CELL *buffer;
  229. int n;
  230. int col;
  231. int nbands;
  232. int row, nrows, ncols;
  233. struct Colors raster_colors;
  234. int r, g, b;
  235. int cell_in_ranges;
  236. nbands = statistics->nbands;
  237. /* build new raster based on current signature and Nstd */
  238. fd = Rast_open_c_new(raster_name);
  239. buffer = Rast_allocate_c_buf();
  240. nrows = Rast_window_rows();
  241. ncols = Rast_window_cols();
  242. for (row = 0; row < nrows; row++) {
  243. read_band_row(band_buffer, band_fd, nbands, row);
  244. for (col = 0; col < ncols; col++) {
  245. buffer[col] = (CELL) 0;
  246. cell_in_ranges = 1;
  247. for (n = 0; n < nbands; n++) {
  248. if (band_buffer[n][col] < statistics->band_range_min[n] ||
  249. band_buffer[n][col] > statistics->band_range_max[n]) {
  250. /* out of at least 1 range */
  251. cell_in_ranges = 0;
  252. }
  253. }
  254. if (cell_in_ranges) {
  255. /* if in range do the assignment */
  256. buffer[col] = (CELL) 1;
  257. }
  258. }
  259. Rast_put_row(fd, buffer, CELL_TYPE);
  260. }
  261. Rast_close(fd);
  262. /* generate and write the color table for the mask */
  263. Rast_init_colors(&raster_colors);
  264. G_str_to_color(statistics->color, &r, &g, &b);
  265. Rast_set_c_color((CELL) 1, r, g, b, &raster_colors);
  266. Rast_write_colors(raster_name, G_mapset(), &raster_colors);
  267. }
  268. /* helpers */
  269. /*!
  270. \brief Helper function for computing min and max range in one band.
  271. Computing min and max range value (distance from mean
  272. dependent on number od std ddevs).
  273. \param statistics pointer to statistics structure
  274. \param band band index
  275. */
  276. void band_range(IClass_statistics * statistics, int band)
  277. {
  278. float dist;
  279. dist = statistics->nstd * statistics->band_stddev[band];
  280. statistics->band_range_min[band] =
  281. statistics->band_mean[band] - dist + 0.5;
  282. statistics->band_range_max[band] =
  283. statistics->band_mean[band] + dist + 0.5;
  284. }
  285. /*!
  286. \brief Helper function for computing mean.
  287. Computing mean value of cell category values
  288. in one band within training area.
  289. \param statistics pointer to statistics structure
  290. \param band band index
  291. \return mean value
  292. */
  293. float mean(IClass_statistics * statistics, int band)
  294. {
  295. return statistics->band_sum[band] / statistics->ncells;
  296. }
  297. /*!
  298. \brief Helper function for standard deviation.
  299. Computing standard deviation of cell category values
  300. in one band within training area.
  301. \param statistics pointer to statistics structure
  302. \param band band index
  303. \return standard deviation
  304. */
  305. float stddev(IClass_statistics * statistics, int band)
  306. {
  307. return sqrt(var(statistics, band, band));
  308. }
  309. /*!
  310. \brief Helper function for computing variance.
  311. Computing variance of cell category values
  312. in one band within training area.
  313. \param statistics pointer to statistics structure
  314. \param band1 band index
  315. \param band2 band index
  316. \return variance
  317. \see var_signature
  318. */
  319. float var(IClass_statistics * statistics, int band1, int band2)
  320. {
  321. float product;
  322. float mean1, mean2;
  323. int n;
  324. product = statistics->band_product[band1][band2];
  325. mean1 = mean(statistics, band1);
  326. mean2 = mean(statistics, band2);
  327. n = statistics->ncells;
  328. return product / n - mean1 * mean2;
  329. }
  330. /*!
  331. \brief Helper function for computing variance for signature file.
  332. Computing variance of cell category values
  333. in one band within training area. Variance is computed
  334. in special way.
  335. \param statistics pointer to statistics structure
  336. \param band1 band index
  337. \param band2 band index
  338. \return variance
  339. \see var
  340. \todo verify the computation
  341. */
  342. float var_signature(IClass_statistics * statistics, int band1, int band2)
  343. {
  344. float product;
  345. float sum1, sum2;
  346. int n;
  347. product = statistics->band_product[band1][band2];
  348. sum1 = statistics->band_sum[band1];
  349. sum2 = statistics->band_sum[band2];
  350. n = statistics->ncells;
  351. return (product - sum1 * sum2 / n) / (n - 1);
  352. }
  353. /* getters */
  354. /*!
  355. \brief Get number of bands.
  356. \param statistics pointer to statistics structure
  357. \param[out] nbands number of bands
  358. */
  359. void I_iclass_statistics_get_nbands(IClass_statistics * statistics,
  360. int *nbands)
  361. {
  362. *nbands = statistics->nbands;
  363. }
  364. /*!
  365. \brief Get category (class).
  366. \param statistics pointer to statistics structure
  367. \param[out] cat category
  368. */
  369. void I_iclass_statistics_get_cat(IClass_statistics * statistics, int *cat)
  370. {
  371. *cat = statistics->cat;
  372. }
  373. /*!
  374. \brief Get category (class) name.
  375. \note \a name is pointer to already allocated
  376. const char * in \a statistics.
  377. You should not free it.
  378. \param statistics pointer to statistics structure
  379. \param[out] name category name
  380. */
  381. void I_iclass_statistics_get_name(IClass_statistics * statistics,
  382. const char **name)
  383. {
  384. *name = statistics->name;
  385. }
  386. /*!
  387. \brief Get category (class) color.
  388. \note \a color is pointer to already allocated
  389. const char * in \a statistics.
  390. You should not free it.
  391. \param statistics pointer to statistics structure
  392. \param[out] color category color
  393. */
  394. void I_iclass_statistics_get_color(IClass_statistics * statistics,
  395. const char **color)
  396. {
  397. *color = statistics->color;
  398. }
  399. /*!
  400. \brief Get number of cells in training areas.
  401. \param statistics pointer to statistics structure
  402. \param[out] ncells number of cells
  403. */
  404. void I_iclass_statistics_get_ncells(IClass_statistics * statistics,
  405. int *ncells)
  406. {
  407. *ncells = statistics->ncells;
  408. }
  409. /*!
  410. \brief Get the multiplier of standard deviation.
  411. \param statistics pointer to statistics structure
  412. \param[out] nstd multiplier of standard deviation
  413. */
  414. void I_iclass_statistics_get_nstd(IClass_statistics * statistics, float *nstd)
  415. {
  416. *nstd = statistics->nstd;
  417. }
  418. /*!
  419. \brief Set the multiplier of standard deviation.
  420. \param statistics pointer to statistics structure
  421. \param nstd multiplier of standard deviation
  422. */
  423. void I_iclass_statistics_set_nstd(IClass_statistics * statistics, float nstd)
  424. {
  425. statistics->nstd = nstd;
  426. }
  427. /*!
  428. \brief Get minimum value in band.
  429. \param statistics pointer to statistics structure
  430. \param band band index
  431. \param[out] min minimum value
  432. \return 1 on success
  433. \return 0 band index out of range
  434. */
  435. int I_iclass_statistics_get_min(IClass_statistics * statistics, int band,
  436. int *min)
  437. {
  438. if (band >= statistics->nbands) {
  439. G_warning(_("Band index out of range"));
  440. return 0;
  441. }
  442. *min = statistics->band_min[band];
  443. return 1;
  444. }
  445. /*!
  446. \brief Get maximum value in band.
  447. \param statistics pointer to statistics structure
  448. \param band band index
  449. \param[out] max maximum value
  450. \return 1 on success
  451. \return 0 band index out of range
  452. */
  453. int I_iclass_statistics_get_max(IClass_statistics * statistics, int band,
  454. int *max)
  455. {
  456. if (band >= statistics->nbands) {
  457. G_warning(_("Band index out of range"));
  458. return 0;
  459. }
  460. *max = statistics->band_max[band];
  461. return 1;
  462. }
  463. /*!
  464. \brief Get sum of values in band.
  465. \param statistics pointer to statistics structure
  466. \param band band index
  467. \param[out] sum sum
  468. \return 1 on success
  469. \return 0 band index out of range
  470. */
  471. int I_iclass_statistics_get_sum(IClass_statistics * statistics, int band,
  472. float *sum)
  473. {
  474. if (band >= statistics->nbands) {
  475. G_warning(_("Band index out of range"));
  476. return 0;
  477. }
  478. *sum = statistics->band_sum[band];
  479. return 1;
  480. }
  481. /*!
  482. \brief Get mean of cell category values in band.
  483. \param statistics pointer to statistics structure
  484. \param band band index
  485. \param[out] mean mean
  486. \return 1 on success
  487. \return 0 band index out of range
  488. */
  489. int I_iclass_statistics_get_mean(IClass_statistics * statistics, int band,
  490. float *mean)
  491. {
  492. if (band >= statistics->nbands) {
  493. G_warning(_("Band index out of range"));
  494. return 0;
  495. }
  496. *mean = statistics->band_mean[band];
  497. return 1;
  498. }
  499. /*!
  500. \brief Get standard deviation of cell category values in band.
  501. \param statistics pointer to statistics structure
  502. \param band band index
  503. \param[out] stddev standard deviation
  504. \return 1 on success
  505. \return 0 band index out of range
  506. */
  507. int I_iclass_statistics_get_stddev(IClass_statistics * statistics, int band,
  508. float *stddev)
  509. {
  510. if (band >= statistics->nbands) {
  511. G_warning(_("Band index out of range"));
  512. return 0;
  513. }
  514. *stddev = statistics->band_stddev[band];
  515. return 1;
  516. }
  517. /*!
  518. \brief Get histogram value in band.
  519. Each band has one value for each raster cell category.
  520. Value is number of cells in category.
  521. \param statistics pointer to statistics structure
  522. \param band band index
  523. \param cat raster cell category
  524. \param[out] value number of cells in category
  525. \return 1 on success
  526. \return 0 band index or cell category value out of range
  527. */
  528. int I_iclass_statistics_get_histo(IClass_statistics * statistics, int band,
  529. int cat, int *value)
  530. {
  531. if (band >= statistics->nbands) {
  532. G_warning(_("Band index out of range"));
  533. return 0;
  534. }
  535. if (cat >= MAX_CATS) {
  536. G_warning(_("Cell category value out of range"));
  537. return 0;
  538. }
  539. *value = statistics->band_histo[band][cat];
  540. return 1;
  541. }
  542. /*!
  543. \brief Get product value
  544. Product value of two bands is sum of products
  545. of cell category values of two bands.
  546. Only cells from training areas are taken into account.
  547. \param statistics statistics object
  548. \param band1 index of first band
  549. \param band2 index of second band
  550. \param[out] value product value
  551. \return 1 on success
  552. \return 0 band index out of range
  553. */
  554. int I_iclass_statistics_get_product(IClass_statistics * statistics, int band1,
  555. int band2, float *value)
  556. {
  557. if (band1 >= statistics->nbands || band2 >= statistics->nbands) {
  558. G_warning(_("Band index out of range"));
  559. return 0;
  560. }
  561. *value = statistics->band_product[band1][band2];
  562. return 1;
  563. }
  564. /*!
  565. \brief Get minimum cell value based on mean and standard deviation for band.
  566. \param statistics pointer to statistics structure
  567. \param band band index
  568. \param[out] min minimum value
  569. \return 1 on success
  570. \return 0 band index out of range
  571. */
  572. int I_iclass_statistics_get_range_min(IClass_statistics * statistics,
  573. int band, int *min)
  574. {
  575. if (band >= statistics->nbands) {
  576. G_warning(_("Band index out of range"));
  577. return 0;
  578. }
  579. *min = statistics->band_range_min[band];
  580. return 1;
  581. }
  582. /*!
  583. \brief Get maximum cell value based on mean and standard deviation for band.
  584. \param statistics pointer to statistics structure
  585. \param band band index
  586. \param[out] max maximum value
  587. \return 1 on success
  588. \return 0 band index out of range
  589. */
  590. int I_iclass_statistics_get_range_max(IClass_statistics * statistics,
  591. int band, int *max)
  592. {
  593. if (band >= statistics->nbands) {
  594. G_warning(_("Band index out of range"));
  595. return 0;
  596. }
  597. *max = statistics->band_range_max[band];
  598. return 1;
  599. }