main.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /****************************************************************************
  2. *
  3. * MODULE: i.cca
  4. * AUTHOR(S): David Satnik, Central Washington University, and
  5. * Ali R. Vali, University of Texas (original contributors)
  6. * Markus Neteler <neteler itc.it>,
  7. * Bernhard Reiter <bernhard intevation.de>,
  8. * Brad Douglas <rez touchofmadness.com>,
  9. * Glynn Clements <glynn gclements.plus.com>,
  10. * Jan-Oliver Wagner <jan intevation.de>
  11. * PURPOSE: canonical components transformation: takes from two to eight
  12. * (raster) band files and a signature file, and outputs the same
  13. * number of raster band files transformed to provide maximum
  14. * separability of the categories indicated by the signatures.
  15. * COPYRIGHT: (C) 1999-2007 by the GRASS Development Team
  16. *
  17. * This program is free software under the GNU General Public
  18. * License (>=v2). Read the file COPYING that comes with GRASS
  19. * for details.
  20. *
  21. *****************************************************************************/
  22. /*
  23. Ali Vali contact info:
  24. Center for Space Research
  25. WRW 402
  26. University of Texas
  27. Austin, TX 78712-1085
  28. (512) 471-6824
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <math.h>
  34. #include <grass/raster.h>
  35. #include <grass/imagery.h>
  36. #include <grass/gmath.h>
  37. #include <grass/glocale.h>
  38. #include "local_proto.h"
  39. int main(int argc, char *argv[])
  40. {
  41. /* Global variable & function declarations */
  42. int i, j, k; /* Loop control variables */
  43. int bands; /* Number of image bands */
  44. int nclass; /* Number of classes */
  45. int samptot; /* Total number of sample points */
  46. double **mu; /* Mean vector for image classes */
  47. double **w; /* Within Class Covariance Matrix */
  48. double **p; /* Between class Covariance Matrix */
  49. double **l; /* Diagonal matrix of eigenvalues */
  50. double **q; /* Transformation matrix */
  51. double ***cov; /* Individual class Covariance Matrix */
  52. double *nsamp; /* Number of samples in a given class */
  53. double *eigval; /* Eigen value vector */
  54. double **eigmat; /* Eigen Matrix */
  55. char tempname[1024];
  56. /* used to make the color tables */
  57. CELL *outbandmax; /* will hold the maximums found in the out maps */
  58. CELL *outbandmin; /* will hold the minimums found in the out maps */
  59. struct Colors color_tbl;
  60. struct Signature sigs;
  61. FILE *sigfp;
  62. struct Ref refs;
  63. int *datafds;
  64. int *outfds;
  65. struct GModule *module;
  66. struct Option *grp_opt, *subgrp_opt, *sig_opt, *out_opt;
  67. /***** Start of main *****/
  68. G_gisinit(argv[0]);
  69. module = G_define_module();
  70. G_add_keyword(_("imagery"));
  71. G_add_keyword(_("statistics"));
  72. G_add_keyword("CCA");
  73. module->description =
  74. _("Canonical components analysis (CCA) "
  75. "program for image processing.");
  76. grp_opt = G_define_standard_option(G_OPT_I_GROUP);
  77. subgrp_opt = G_define_standard_option(G_OPT_I_GROUP);
  78. subgrp_opt->key = "subgroup";
  79. subgrp_opt->description = _("Name of input imagery subgroup");
  80. sig_opt = G_define_option();
  81. sig_opt->key = "signature";
  82. sig_opt->type = TYPE_STRING;
  83. sig_opt->required = YES;
  84. sig_opt->key_desc = "name";
  85. sig_opt->description = _("File containing spectral signatures");
  86. out_opt = G_define_standard_option(G_OPT_R_OUTPUT);
  87. out_opt->description = _("Output raster map prefix name");
  88. if (G_parser(argc, argv))
  89. exit(EXIT_FAILURE);
  90. /* check group, subgroup */
  91. I_init_group_ref(&refs);
  92. if (I_find_group(grp_opt->answer) <= 0)
  93. G_fatal_error(_("Unknown imagery group."));
  94. if (I_get_subgroup_ref(grp_opt->answer, subgrp_opt->answer, &refs) <= 0)
  95. G_fatal_error(_("Unable to find subgroup reference information."));
  96. /* open and input the signatures file */
  97. if ((sigfp =
  98. I_fopen_signature_file_old(grp_opt->answer, subgrp_opt->answer,
  99. sig_opt->answer)) == NULL)
  100. G_fatal_error(_("Unable to open the signature file"));
  101. I_init_signatures(&sigs, refs.nfiles);
  102. if (I_read_signatures(sigfp, &sigs) < 0)
  103. G_fatal_error(_("Error while reading the signatures file."));
  104. fclose(sigfp);
  105. nclass = sigs.nsigs;
  106. if (nclass < 2)
  107. G_fatal_error(_("Need at least two signatures in signature file."));
  108. /* check the number of input bands */
  109. bands = refs.nfiles;
  110. /*memory allocation*/
  111. mu = G_alloc_matrix(nclass, bands);
  112. w = G_alloc_matrix(bands, bands);
  113. p = G_alloc_matrix(bands, bands);
  114. l = G_alloc_matrix(bands, bands);
  115. q = G_alloc_matrix(bands, bands);
  116. eigmat = G_alloc_matrix(bands, bands);
  117. nsamp = G_alloc_vector(nclass);
  118. eigval = G_alloc_vector(bands);
  119. cov = (double***)G_calloc(nclass, sizeof(double**));
  120. for(i = 0; i < nclass; i++)
  121. {
  122. cov[i] = G_alloc_matrix(bands,bands);
  123. }
  124. outbandmax = (CELL*)G_calloc(nclass, sizeof(CELL));
  125. outbandmin = (CELL*)G_calloc(nclass, sizeof(CELL));
  126. datafds = (int*)G_calloc(nclass, sizeof(int));
  127. outfds = (int*)G_calloc(nclass, sizeof(int));
  128. /*
  129. Here is where the information regarding
  130. a) Number of samples per class
  131. b) Covariance matrix for each class
  132. are read into the program
  133. */
  134. samptot = 0;
  135. for (i = 1; i <= nclass; i++) {
  136. nsamp[i] = sigs.sig[i - 1].npoints;
  137. samptot += nsamp[i];
  138. for (j = 1; j <= bands; j++) {
  139. mu[i][j] = sigs.sig[i - 1].mean[j - 1];
  140. for (k = 1; k <= j; k++)
  141. cov[i][j][k] = cov[i][k][j] =
  142. sigs.sig[i - 1].var[j - 1][k - 1];
  143. }
  144. }
  145. within(samptot, nclass, nsamp, cov, w, bands);
  146. between(samptot, nclass, nsamp, mu, p, bands);
  147. G_math_d_copy(w[0], eigmat[0], bands*bands);
  148. G_math_eigen(eigmat, eigval, bands);
  149. G_math_egvorder(eigval, eigmat, bands);
  150. setdiag(eigval, bands, l);
  151. getsqrt(w, bands, l, eigmat);
  152. solveq(q, bands, w, p);
  153. G_math_d_copy(q[0], eigmat[0], bands*bands);
  154. G_math_eigen(eigmat, eigval, bands);
  155. G_math_egvorder(eigval, eigmat, bands);
  156. G_math_d_AB(eigmat, w, q, bands, bands, bands);
  157. for(i = 0; i < bands; i++)
  158. {
  159. G_verbose_message("%i. eigen value: %+6.5f", i, eigval[i]);
  160. G_verbose_message("eigen vector:");
  161. for(j = 0; j < bands; j++)
  162. G_verbose_message("%+6.5f ", eigmat[i][j]);
  163. }
  164. /* open the cell maps */
  165. for (i = 1; i <= bands; i++) {
  166. outbandmax[i] = (CELL) 0;
  167. outbandmin[i] = (CELL) 0;
  168. datafds[i] = Rast_open_old(refs.file[i - 1].name,
  169. refs.file[i - 1].mapset);
  170. sprintf(tempname, "%s.%d", out_opt->answer, i);
  171. outfds[i] = Rast_open_c_new(tempname);
  172. }
  173. /* do the transform */
  174. transform(datafds, outfds, Rast_window_rows(), Rast_window_cols(), q, bands,
  175. outbandmin, outbandmax);
  176. /* make grey scale color table */
  177. Rast_init_colors(&color_tbl);
  178. /* close the cell maps */
  179. for (i = 1; i <= bands; i++) {
  180. Rast_close(datafds[i]);
  181. Rast_close(outfds[i]);
  182. if (outbandmin[i] < (CELL) 0 || outbandmax[i] > (CELL) 255) {
  183. G_warning(_("The output cell map <%s.%d> has values "
  184. "outside the 0-255 range."), out_opt->answer, i);
  185. }
  186. Rast_make_grey_scale_colors(&color_tbl, 0, outbandmax[i]);
  187. sprintf(tempname, "%s.%d", out_opt->answer, i);
  188. /* write a color table */
  189. Rast_write_colors(tempname, G_mapset(), &color_tbl);
  190. }
  191. I_free_signatures(&sigs);
  192. I_free_group_ref(&refs);
  193. /*free memory*/
  194. G_free_matrix(mu);
  195. G_free_matrix(w);
  196. G_free_matrix(p);
  197. G_free_matrix(l);
  198. G_free_matrix(q);
  199. G_free_matrix(eigmat);
  200. for(i = 0; i < nclass; i++)
  201. G_free_matrix(cov[i]);
  202. G_free(cov);
  203. G_free_vector(nsamp);
  204. G_free_vector(eigval);
  205. G_free(outbandmax);
  206. G_free(outbandmin);
  207. G_free(datafds);
  208. G_free(outfds);
  209. exit(EXIT_SUCCESS);
  210. }