iclass_statistics.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  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(statistics->name);
  90. G_free(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() read value: %d", value);
  192. if (value < 0 || value > MAX_CATS - 1) {
  193. G_warning(_("prepare_signature: data error."));
  194. return 0;
  195. }
  196. statistics->band_sum[b] += value; /* sum for means */
  197. statistics->band_histo[b][value]++; /* histogram */
  198. if (statistics->band_min[b] > value)
  199. statistics->band_min[b] = value; /* absolute min, max */
  200. if (statistics->band_max[b] < value) {
  201. statistics->band_max[b] = value;
  202. G_debug(5,
  203. "make_statistics() statistics->band_max[%d]: %d",
  204. b, statistics->band_max[b]);
  205. }
  206. for (b2 = 0; b2 <= b; b2++) /* products for variance */
  207. statistics->band_product[b][b2] +=
  208. value * band_buffer[b2][x];
  209. }
  210. }
  211. }
  212. statistics->ncells += ncells;
  213. return 1;
  214. }
  215. /*!
  216. \brief Create raster map based on statistics.
  217. \param statistics pointer to statistics structure
  218. \param band_buffer buffer to read band rows into
  219. \param band_fd band files descriptors
  220. \param raster_name name of new raster map
  221. */
  222. void create_raster(IClass_statistics * statistics, CELL ** band_buffer,
  223. int *band_fd, const char *raster_name)
  224. {
  225. int fd;
  226. CELL *buffer;
  227. int n;
  228. int col;
  229. int nbands;
  230. int row, nrows, ncols;
  231. struct Colors raster_colors;
  232. int r, g, b;
  233. int cell_in_ranges;
  234. nbands = statistics->nbands;
  235. /* build new raster based on current signature and Nstd */
  236. fd = Rast_open_c_new(raster_name);
  237. buffer = Rast_allocate_c_buf();
  238. nrows = Rast_window_rows();
  239. ncols = Rast_window_cols();
  240. for (row = 0; row < nrows; row++) {
  241. read_band_row(band_buffer, band_fd, nbands, row);
  242. for (col = 0; col < ncols; col++) {
  243. buffer[col] = (CELL) 0;
  244. cell_in_ranges = 1;
  245. for (n = 0; n < nbands; n++) {
  246. if (band_buffer[n][col] < statistics->band_range_min[n] ||
  247. band_buffer[n][col] > statistics->band_range_max[n]) {
  248. /* out of at least 1 range */
  249. cell_in_ranges = 0;
  250. }
  251. }
  252. if (cell_in_ranges) {
  253. /* if in range do the assignment */
  254. buffer[col] = (CELL) 1;
  255. }
  256. }
  257. Rast_put_row(fd, buffer, CELL_TYPE);
  258. }
  259. Rast_close(fd);
  260. /* generate and write the color table for the mask */
  261. Rast_init_colors(&raster_colors);
  262. G_str_to_color(statistics->color, &r, &g, &b);
  263. Rast_set_c_color((CELL) 1, r, g, b, &raster_colors);
  264. Rast_write_colors(raster_name, G_mapset(), &raster_colors);
  265. }
  266. /* helpers */
  267. /*!
  268. \brief Helper function for computing min and max range in one band.
  269. Computing min and max range value (distance from mean
  270. dependent on number od std ddevs).
  271. \param statistics pointer to statistics structure
  272. \param band band index
  273. */
  274. void band_range(IClass_statistics * statistics, int band)
  275. {
  276. float dist;
  277. dist = statistics->nstd * statistics->band_stddev[band];
  278. statistics->band_range_min[band] =
  279. statistics->band_mean[band] - dist + 0.5;
  280. statistics->band_range_max[band] =
  281. statistics->band_mean[band] + dist + 0.5;
  282. }
  283. /*!
  284. \brief Helper function for computing mean.
  285. Computing mean value of cell category values
  286. in one band within training area.
  287. \param statistics pointer to statistics structure
  288. \param band band index
  289. \return mean value
  290. */
  291. float mean(IClass_statistics * statistics, int band)
  292. {
  293. return statistics->band_sum[band] / statistics->ncells;
  294. }
  295. /*!
  296. \brief Helper function for standard deviation.
  297. Computing standard deviation of cell category values
  298. in one band within training area.
  299. \param statistics pointer to statistics structure
  300. \param band band index
  301. \return standard deviation
  302. */
  303. float stddev(IClass_statistics * statistics, int band)
  304. {
  305. return sqrt(var(statistics, band, band));
  306. }
  307. /*!
  308. \brief Helper function for computing variance.
  309. Computing variance of cell category values
  310. in one band within training area.
  311. \param statistics pointer to statistics structure
  312. \param band1 band index
  313. \param band2 band index
  314. \return variance
  315. \see var_signature
  316. */
  317. float var(IClass_statistics * statistics, int band1, int band2)
  318. {
  319. float product;
  320. float mean1, mean2;
  321. int n;
  322. product = statistics->band_product[band1][band2];
  323. mean1 = mean(statistics, band1);
  324. mean2 = mean(statistics, band2);
  325. n = statistics->ncells;
  326. return product / n - mean1 * mean2;
  327. }
  328. /*!
  329. \brief Helper function for computing variance for signature file.
  330. Computing variance of cell category values
  331. in one band within training area. Variance is computed
  332. in special way.
  333. \param statistics pointer to statistics structure
  334. \param band1 band index
  335. \param band2 band index
  336. \return variance
  337. \see var
  338. \todo verify the computation
  339. */
  340. float var_signature(IClass_statistics * statistics, int band1, int band2)
  341. {
  342. float product;
  343. float sum1, sum2;
  344. int n;
  345. product = statistics->band_product[band1][band2];
  346. sum1 = statistics->band_sum[band1];
  347. sum2 = statistics->band_sum[band2];
  348. n = statistics->ncells;
  349. return (product - sum1 * sum2 / n) / (n - 1);
  350. }
  351. /* getters */
  352. /*!
  353. \brief Get number of bands.
  354. \param statistics pointer to statistics structure
  355. \param[out] nbands number of bands
  356. */
  357. void I_iclass_statistics_get_nbands(IClass_statistics * statistics,
  358. int *nbands)
  359. {
  360. *nbands = statistics->nbands;
  361. }
  362. /*!
  363. \brief Get category (class).
  364. \param statistics pointer to statistics structure
  365. \param[out] cat category
  366. */
  367. void I_iclass_statistics_get_cat(IClass_statistics * statistics, int *cat)
  368. {
  369. *cat = statistics->cat;
  370. }
  371. /*!
  372. \brief Get category (class) name.
  373. \note \a name is pointer to already allocated
  374. const char * in \a statistics.
  375. You should not free it.
  376. \param statistics pointer to statistics structure
  377. \param[out] name category name
  378. */
  379. void I_iclass_statistics_get_name(IClass_statistics * statistics,
  380. const char **name)
  381. {
  382. *name = statistics->name;
  383. }
  384. /*!
  385. \brief Get category (class) color.
  386. \note \a color is pointer to already allocated
  387. const char * in \a statistics.
  388. You should not free it.
  389. \param statistics pointer to statistics structure
  390. \param[out] color category color
  391. */
  392. void I_iclass_statistics_get_color(IClass_statistics * statistics,
  393. const char **color)
  394. {
  395. *color = statistics->color;
  396. }
  397. /*!
  398. \brief Get number of cells in training areas.
  399. \param statistics pointer to statistics structure
  400. \param[out] ncells number of cells
  401. */
  402. void I_iclass_statistics_get_ncells(IClass_statistics * statistics,
  403. int *ncells)
  404. {
  405. *ncells = statistics->ncells;
  406. }
  407. /*!
  408. \brief Get the multiplier of standard deviation.
  409. \param statistics pointer to statistics structure
  410. \param[out] nstd multiplier of standard deviation
  411. */
  412. void I_iclass_statistics_get_nstd(IClass_statistics * statistics, float *nstd)
  413. {
  414. *nstd = statistics->nstd;
  415. }
  416. /*!
  417. \brief Set the multiplier of standard deviation.
  418. \param statistics pointer to statistics structure
  419. \param nstd multiplier of standard deviation
  420. */
  421. void I_iclass_statistics_set_nstd(IClass_statistics * statistics, float nstd)
  422. {
  423. statistics->nstd = nstd;
  424. }
  425. /*!
  426. \brief Get minimum value in band.
  427. \param statistics pointer to statistics structure
  428. \param band band index
  429. \param[out] min minimum value
  430. \return 1 on success
  431. \return 0 band index out of range
  432. */
  433. int I_iclass_statistics_get_min(IClass_statistics * statistics, int band,
  434. int *min)
  435. {
  436. if (band >= statistics->nbands) {
  437. G_warning(_("Band index out of range"));
  438. return 0;
  439. }
  440. *min = statistics->band_min[band];
  441. return 1;
  442. }
  443. /*!
  444. \brief Get maximum value in band.
  445. \param statistics pointer to statistics structure
  446. \param band band index
  447. \param[out] max maximum value
  448. \return 1 on success
  449. \return 0 band index out of range
  450. */
  451. int I_iclass_statistics_get_max(IClass_statistics * statistics, int band,
  452. int *max)
  453. {
  454. if (band >= statistics->nbands) {
  455. G_warning(_("Band index out of range"));
  456. return 0;
  457. }
  458. *max = statistics->band_max[band];
  459. return 1;
  460. }
  461. /*!
  462. \brief Get sum of values in band.
  463. \param statistics pointer to statistics structure
  464. \param band band index
  465. \param[out] sum sum
  466. \return 1 on success
  467. \return 0 band index out of range
  468. */
  469. int I_iclass_statistics_get_sum(IClass_statistics * statistics, int band,
  470. float *sum)
  471. {
  472. if (band >= statistics->nbands) {
  473. G_warning(_("Band index out of range"));
  474. return 0;
  475. }
  476. *sum = statistics->band_sum[band];
  477. return 1;
  478. }
  479. /*!
  480. \brief Get mean of cell category values in band.
  481. \param statistics pointer to statistics structure
  482. \param band band index
  483. \param[out] mean mean
  484. \return 1 on success
  485. \return 0 band index out of range
  486. */
  487. int I_iclass_statistics_get_mean(IClass_statistics * statistics, int band,
  488. float *mean)
  489. {
  490. if (band >= statistics->nbands) {
  491. G_warning(_("Band index out of range"));
  492. return 0;
  493. }
  494. *mean = statistics->band_mean[band];
  495. return 1;
  496. }
  497. /*!
  498. \brief Get standard deviation of cell category values in band.
  499. \param statistics pointer to statistics structure
  500. \param band band index
  501. \param[out] stddev standard deviation
  502. \return 1 on success
  503. \return 0 band index out of range
  504. */
  505. int I_iclass_statistics_get_stddev(IClass_statistics * statistics, int band,
  506. float *stddev)
  507. {
  508. if (band >= statistics->nbands) {
  509. G_warning(_("Band index out of range"));
  510. return 0;
  511. }
  512. *stddev = statistics->band_stddev[band];
  513. return 1;
  514. }
  515. /*!
  516. \brief Get histogram value in band.
  517. Each band has one value for each raster cell category.
  518. Value is number of cells in category.
  519. \param statistics pointer to statistics structure
  520. \param band band index
  521. \param cat raster cell category
  522. \param[out] value number of cells in category
  523. \return 1 on success
  524. \return 0 band index or cell category value out of range
  525. */
  526. int I_iclass_statistics_get_histo(IClass_statistics * statistics, int band,
  527. int cat, int *value)
  528. {
  529. if (band >= statistics->nbands) {
  530. G_warning(_("Band index out of range"));
  531. return 0;
  532. }
  533. if (cat >= MAX_CATS) {
  534. G_warning(_("Cell category value out of range"));
  535. return 0;
  536. }
  537. *value = statistics->band_histo[band][cat];
  538. return 1;
  539. }
  540. /*!
  541. \brief Get product value
  542. Product value of two bands is sum of products
  543. of cell category values of two bands.
  544. Only cells from training areas are taken into account.
  545. \param statistics statistics object
  546. \param band1 index of first band
  547. \param band2 index of second band
  548. \param[out] value product value
  549. \return 1 on success
  550. \return 0 band index out of range
  551. */
  552. int I_iclass_statistics_get_product(IClass_statistics * statistics, int band1,
  553. int band2, float *value)
  554. {
  555. if (band1 >= statistics->nbands || band2 >= statistics->nbands) {
  556. G_warning(_("Band index out of range"));
  557. return 0;
  558. }
  559. *value = statistics->band_product[band1][band2];
  560. return 1;
  561. }
  562. /*!
  563. \brief Get minimum cell value based on mean and standard deviation for band.
  564. \param statistics pointer to statistics structure
  565. \param band band index
  566. \param[out] min minumum value
  567. \return 1 on success
  568. \return 0 band index out of range
  569. */
  570. int I_iclass_statistics_get_range_min(IClass_statistics * statistics,
  571. int band, int *min)
  572. {
  573. if (band >= statistics->nbands) {
  574. G_warning(_("Band index out of range"));
  575. return 0;
  576. }
  577. *min = statistics->band_range_min[band];
  578. return 1;
  579. }
  580. /*!
  581. \brief Get maximum cell value based on mean and standard deviation for band.
  582. \param statistics pointer to statistics structure
  583. \param band band index
  584. \param[out] max maximum value
  585. \return 1 on success
  586. \return 0 band index out of range
  587. */
  588. int I_iclass_statistics_get_range_max(IClass_statistics * statistics,
  589. int band, int *max)
  590. {
  591. if (band >= statistics->nbands) {
  592. G_warning(_("Band index out of range"));
  593. return 0;
  594. }
  595. *max = statistics->band_range_max[band];
  596. return 1;
  597. }