main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /****************************************************************************
  2. *
  3. * MODULE: i.cluster
  4. * AUTHOR(S): Michael Shapiro (USACERL) and Tao Wen (UIUC)
  5. * (original contributors)
  6. * Markus Neteler <neteler itc.it>,
  7. * Roberto Flor <flor itc.it>,
  8. * Bernhard Reiter <bernhard intevation.de>,
  9. * Brad Douglas <rez touchofmadness.com>,
  10. * Glynn Clements <glynn gclements.plus.com>,
  11. * Jan-Oliver Wagner <jan intevation.de>
  12. * PURPOSE: builds pixel clusters based on multi-image pixel values
  13. * COPYRIGHT: (C) 1999-2008 by the GRASS Development Team
  14. *
  15. * This program is free software under the GNU General Public
  16. * License (>=v2). Read the file COPYING that comes with GRASS
  17. * for details.
  18. *
  19. *****************************************************************************/
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <grass/gis.h>
  23. #include <grass/raster.h>
  24. #include <grass/glocale.h>
  25. #define GLOBAL
  26. #include "global.h"
  27. #include "local_proto.h"
  28. struct Cluster C;
  29. struct Signature in_sig;
  30. int maxclass;
  31. double conv;
  32. double sep;
  33. int iters;
  34. int mcs;
  35. char *group;
  36. char *subgroup;
  37. struct Ref ref;
  38. char *outsigfile;
  39. char *insigfile;
  40. char *reportfile;
  41. DCELL **cell;
  42. int *cellfd;
  43. FILE *report;
  44. int sample_rows, sample_cols;
  45. time_t start_time;
  46. static int interrupted = 0;
  47. int main(int argc, char *argv[])
  48. {
  49. int count;
  50. int n;
  51. int row, nrows;
  52. int col, ncols;
  53. DCELL *x;
  54. struct Cell_head window;
  55. FILE *fd;
  56. struct GModule *module;
  57. struct
  58. {
  59. struct Option *group_name, *subgroup_name, *out_sig, *seed_sig,
  60. *class, *sample_interval, *iterations, *separation,
  61. *convergence, *min_size, *report_file;
  62. } parm;
  63. G_gisinit(argv[0]);
  64. module = G_define_module();
  65. G_add_keyword(_("imagery"));
  66. G_add_keyword(_("classification"));
  67. G_add_keyword(_("signatures"));
  68. module->label =
  69. _("Generates spectral signatures for land cover "
  70. "types in an image using a clustering algorithm.");
  71. module->description =
  72. _("The resulting signature file is used as input for i.maxlik, "
  73. "to generate an unsupervised image classification.");
  74. parm.group_name = G_define_standard_option(G_OPT_I_GROUP);
  75. parm.subgroup_name = G_define_standard_option(G_OPT_I_SUBGROUP);
  76. parm.out_sig = G_define_option();
  77. parm.out_sig->key = "signaturefile";
  78. parm.out_sig->type = TYPE_STRING;
  79. parm.out_sig->key_desc = "name";
  80. parm.out_sig->required = YES;
  81. parm.out_sig->gisprompt = "old,sig,sigfile";
  82. parm.out_sig->description = _("Name for output file containing result signatures");
  83. parm.class = G_define_option();
  84. parm.class->key = "classes";
  85. parm.class->type = TYPE_INTEGER;
  86. parm.class->options = "1-255";
  87. parm.class->required = YES;
  88. parm.class->description = _("Initial number of classes");
  89. parm.class->guisection = _("Settings");
  90. parm.seed_sig = G_define_option();
  91. parm.seed_sig->key = "seed";
  92. parm.seed_sig->required = NO;
  93. parm.seed_sig->type = TYPE_STRING;
  94. parm.seed_sig->key_desc = "name";
  95. parm.seed_sig->description = _("Name of file containing initial signatures");
  96. parm.sample_interval = G_define_option();
  97. parm.sample_interval->key = "sample";
  98. parm.sample_interval->key_desc = "row_interval,col_interval";
  99. parm.sample_interval->type = TYPE_INTEGER;
  100. parm.sample_interval->required = NO;
  101. parm.sample_interval->description =
  102. _("Sampling intervals (by row and col); default: ~10,000 pixels");
  103. parm.sample_interval->guisection = _("Settings");
  104. parm.iterations = G_define_option();
  105. parm.iterations->key = "iterations";
  106. parm.iterations->type = TYPE_INTEGER;
  107. parm.iterations->required = NO;
  108. parm.iterations->description = _("Maximum number of iterations");
  109. parm.iterations->answer = "30";
  110. parm.iterations->guisection = _("Settings");
  111. parm.convergence = G_define_option();
  112. parm.convergence->key = "convergence";
  113. parm.convergence->type = TYPE_DOUBLE;
  114. parm.convergence->required = NO;
  115. parm.convergence->options = "0-100";
  116. parm.convergence->description = _("Percent convergence");
  117. parm.convergence->answer = "98.0";
  118. parm.convergence->guisection = _("Settings");
  119. parm.separation = G_define_option();
  120. parm.separation->key = "separation";
  121. parm.separation->type = TYPE_DOUBLE;
  122. parm.separation->required = NO;
  123. parm.separation->description = _("Cluster separation");
  124. parm.separation->answer = "0.0";
  125. parm.separation->guisection = _("Settings");
  126. parm.min_size = G_define_option();
  127. parm.min_size->key = "min_size";
  128. parm.min_size->type = TYPE_INTEGER;
  129. parm.min_size->required = NO;
  130. parm.min_size->description = _("Minimum number of pixels in a class");
  131. parm.min_size->answer = "17";
  132. parm.min_size->guisection = _("Settings");
  133. parm.report_file = G_define_standard_option(G_OPT_F_OUTPUT);
  134. parm.report_file->key = "reportfile";
  135. parm.report_file->required = NO;
  136. parm.report_file->description = _("Name for output file containing final report");
  137. if (G_parser(argc, argv))
  138. exit(EXIT_FAILURE);
  139. G_get_window(&window);
  140. nrows = Rast_window_rows();
  141. ncols = Rast_window_cols();
  142. I_cluster_clear(&C);
  143. group = parm.group_name->answer; /* a required parameter */
  144. subgroup = parm.subgroup_name->answer; /* required */
  145. outsigfile = parm.out_sig->answer;
  146. if (sscanf(parm.class->answer, "%d", &maxclass) != 1 || maxclass < 1
  147. || maxclass > 255) {
  148. G_fatal_error(_("Illegal number of initial classes (%s)"),
  149. parm.class->answer);
  150. }
  151. insigfile = parm.seed_sig->answer;
  152. if (parm.sample_interval->answer) {
  153. if (sscanf
  154. (parm.sample_interval->answer, "%d,%d", &sample_rows,
  155. &sample_cols) != 2 || sample_rows < 1 || sample_cols < 1 ||
  156. sample_rows > nrows || sample_cols > ncols) {
  157. G_fatal_error(_("Illegal value(s) of sample intervals (%s)"),
  158. parm.sample_interval->answer);
  159. }
  160. }
  161. else {
  162. sample_rows = nrows / 100;
  163. if (sample_rows < 1)
  164. sample_rows = 1;
  165. sample_cols = ncols / 100;
  166. if (sample_cols < 1)
  167. sample_cols = 1;
  168. }
  169. if (sscanf(parm.iterations->answer, "%d", &iters) != 1 || iters < 1) {
  170. G_fatal_error(_("Illegal value of iterations (%s)"),
  171. parm.iterations->answer);
  172. }
  173. if (sscanf(parm.convergence->answer, "%lf", &conv) != 1 || conv < 0.0 ||
  174. conv > 100.0) {
  175. G_fatal_error(_("Illegal value of convergence (%s)"),
  176. parm.convergence->answer);
  177. }
  178. if (sscanf(parm.separation->answer, "%lf", &sep) != 1 || sep < 0.0) {
  179. G_fatal_error(_("Illegal value of separation (%s)"),
  180. parm.separation->answer);
  181. }
  182. if (sscanf(parm.min_size->answer, "%d", &mcs) != 1 || mcs < 2) {
  183. G_fatal_error(_("Illegal value of min_size (%s)"),
  184. parm.min_size->answer);
  185. }
  186. if ((reportfile = parm.report_file->answer) == NULL)
  187. report = fopen(G_DEV_NULL, "w");
  188. else
  189. report = fopen(reportfile, "w");
  190. if (report == NULL) {
  191. G_fatal_error(_("Unable to create report file <%s>"),
  192. reportfile);
  193. }
  194. open_files();
  195. fprintf(report,
  196. _("#################### CLUSTER (%s) ####################\n\n"),
  197. G_date());
  198. fprintf(report, _("Location: %s\n"), G_location());
  199. fprintf(report, _("Mapset: %s\n"), G_mapset());
  200. fprintf(report, _("Group: %s\n"), group);
  201. fprintf(report, _("Subgroup: %s\n"), subgroup);
  202. for (n = 0; n < ref.nfiles; n++) {
  203. fprintf(report, _(" %s\n"),
  204. G_fully_qualified_name(ref.file[n].name, ref.file[n].mapset));
  205. }
  206. fprintf(report, _("Result signature file: %s\n"), outsigfile);
  207. fprintf(report, "\n");
  208. fprintf(report, _("Region\n"));
  209. fprintf(report, _(" North: %12.2f East: %12.2f\n"), window.north,
  210. window.east);
  211. fprintf(report, _(" South: %12.2f West: %12.2f\n"), window.south,
  212. window.west);
  213. fprintf(report, _(" Res: %12.2f Res: %12.2f\n"), window.ns_res,
  214. window.ew_res);
  215. fprintf(report, _(" Rows: %12d Cols: %12d Cells: %d\n"), nrows, ncols,
  216. nrows * ncols);
  217. fprintf(report, _("Mask: %s\n"), Rast_mask_info());
  218. fprintf(report, "\n");
  219. fprintf(report, _("Cluster parameters\n"));
  220. fprintf(report, _(" Number of initial classes: %d"), maxclass);
  221. if (insigfile)
  222. fprintf(report, _(" [from signature file %s]"), insigfile);
  223. fprintf(report, "\n");
  224. fprintf(report, _(" Minimum class size: %d\n"), mcs);
  225. fprintf(report, _(" Minimum class separation: %f\n"), sep);
  226. fprintf(report, _(" Percent convergence: %f\n"), conv);
  227. fprintf(report, _(" Maximum number of iterations: %d\n"), iters);
  228. fprintf(report, "\n");
  229. fprintf(report, _(" Row sampling interval: %d\n"), sample_rows);
  230. fprintf(report, _(" Col sampling interval: %d\n"), sample_cols);
  231. fprintf(report, "\n");
  232. fflush(report);
  233. x = (DCELL *) G_malloc(ref.nfiles * sizeof(DCELL));
  234. I_cluster_begin(&C, ref.nfiles);
  235. count = 0;
  236. G_message(_("Reading raster maps..."));
  237. for (row = sample_rows - 1; row < nrows; row += sample_rows) {
  238. G_percent(row, nrows, 2);
  239. for (n = 0; n < ref.nfiles; n++)
  240. Rast_get_d_row(cellfd[n], cell[n], row);
  241. for (col = sample_cols - 1; col < ncols; col += sample_cols) {
  242. count++;
  243. for (n = 0; n < ref.nfiles; n++)
  244. x[n] = cell[n][col];
  245. if (I_cluster_point(&C, x) < 0)
  246. G_fatal_error(_("Out of Memory. Please run again and choose a "
  247. "smaller sample size."));
  248. }
  249. }
  250. G_percent(nrows, nrows, 2);
  251. fprintf(report, _("Sample size: %d points\n"), C.npoints);
  252. fprintf(report, "\n");
  253. if (count < 2)
  254. G_fatal_error(_("Not enough sample points. Please run again and "
  255. "choose a larger sample size."));
  256. if (C.npoints < 2)
  257. G_fatal_error(_("Not enough non-zero sample data points. Check "
  258. "your current region (and mask)."));
  259. for (n = 0; n < ref.nfiles; n++) {
  260. G_free(cell[n]);
  261. Rast_close(cellfd[n]);
  262. }
  263. G_free(x);
  264. start_time = time(NULL);
  265. I_cluster_exec(&C, maxclass, iters, conv, sep, mcs, checkpoint,
  266. &interrupted);
  267. fprintf(report, _("\n########## final results #############\n"));
  268. fprintf(report, _("%d classes (convergence=%.1f%%)\n"),
  269. I_cluster_nclasses(&C, mcs), (double)C.percent_stable);
  270. print_separability(report, &C);
  271. print_class_means(report, &C);
  272. if ((fd =
  273. I_fopen_signature_file_new(group, subgroup, outsigfile)) != NULL) {
  274. I_write_signatures(fd, &C.S);
  275. fclose(fd);
  276. }
  277. else {
  278. G_fatal_error(_("Unable to create signature file <%s> for group "
  279. "<%s>, subsgroup <%s>"), outsigfile, group, subgroup);
  280. }
  281. fprintf(report,
  282. _("\n\n#################### CLASSES ####################\n"));
  283. fprintf(report, _("\n%d classes, %.2f%% points stable\n"),
  284. I_cluster_nclasses(&C, 1), (double)C.percent_stable);
  285. fprintf(report, _("\n######## CLUSTER END (%s) ########\n"), G_date());
  286. fclose(report);
  287. G_done_msg(_("File <%s> created."),
  288. outsigfile);
  289. exit(EXIT_SUCCESS);
  290. }