parse_args.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* PURPOSE: Parse and validate the input */
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <grass/gis.h>
  5. #include <grass/glocale.h>
  6. #include <grass/raster.h>
  7. #include "iseg.h"
  8. int parse_args(int argc, char *argv[], struct globals *globals)
  9. {
  10. struct Option *group, *seeds, *bounds, *output,
  11. *method, *similarity, *threshold, *min_segment_size,
  12. #ifdef _OR_SHAPE_
  13. *shape_weight, *smooth_weight,
  14. #endif
  15. *mem;
  16. struct Flag *diagonal, *weighted;
  17. struct Option *outband, *endt;
  18. /* required parameters */
  19. group = G_define_standard_option(G_OPT_I_GROUP);
  20. output = G_define_standard_option(G_OPT_R_OUTPUT);
  21. threshold = G_define_option();
  22. threshold->key = "threshold";
  23. threshold->type = TYPE_DOUBLE;
  24. threshold->required = YES;
  25. threshold->label = _("Difference threshold between 0 and 1");
  26. threshold->description = _("Threshold = 0 merges only identical segments; threshold = 1 merges all");
  27. /* optional parameters */
  28. method = G_define_option();
  29. method->key = "method";
  30. method->type = TYPE_STRING;
  31. method->required = NO;
  32. method->answer = "region_growing";
  33. method->options = "region_growing,mean_shift,watershed";
  34. method->description = _("Segmentation method");
  35. method->guisection = _("Settings");
  36. similarity = G_define_option();
  37. similarity->key = "similarity";
  38. similarity->type = TYPE_STRING;
  39. similarity->required = NO;
  40. similarity->answer = "euclidean";
  41. similarity->options = "euclidean,manhattan";
  42. similarity->description = _("Similarity calculation method");
  43. similarity->guisection = _("Settings");
  44. min_segment_size = G_define_option();
  45. min_segment_size->key = "minsize";
  46. min_segment_size->type = TYPE_INTEGER;
  47. min_segment_size->required = NO;
  48. min_segment_size->answer = "1";
  49. min_segment_size->options = "1-100000";
  50. min_segment_size->label = _("Minimum number of cells in a segment");
  51. min_segment_size->description =
  52. _("The final step will merge small segments with their best neighbor");
  53. min_segment_size->guisection = _("Settings");
  54. #ifdef _OR_SHAPE_
  55. radio_weight = G_define_option();
  56. radio_weight->key = "radio_weight";
  57. radio_weight->type = TYPE_DOUBLE;
  58. radio_weight->required = NO;
  59. radio_weight->answer = "1";
  60. radio_weight->options = "0-1";
  61. radio_weight->label =
  62. _("Importance of radiometric (input raster) values relative to shape");
  63. radio_weight->guisection = _("Settings");
  64. smooth_weight = G_define_option();
  65. smooth_weight->key = "smooth_weight";
  66. smooth_weight->type = TYPE_DOUBLE;
  67. smooth_weight->required = NO;
  68. smooth_weight->answer = "0.5";
  69. smooth_weight->options = "0-1";
  70. smooth_weight->label =
  71. _("Importance of smoothness relative to compactness");
  72. smooth_weight->guisection = _("Settings");
  73. #endif
  74. mem = G_define_option();
  75. mem->key = "memory";
  76. mem->type = TYPE_INTEGER;
  77. mem->required = NO;
  78. mem->answer = "300";
  79. mem->description = _("Memory in MB");
  80. /* TODO input for distance function */
  81. /* debug parameters */
  82. endt = G_define_option();
  83. endt->key = "iterations";
  84. endt->type = TYPE_INTEGER;
  85. endt->required = NO;
  86. endt->answer = "20";
  87. endt->description = _("Maximum number of iterations");
  88. endt->guisection = _("Settings");
  89. /* Using raster for seeds
  90. * Low priority TODO: allow vector points/centroids seed input. */
  91. seeds = G_define_standard_option(G_OPT_R_INPUT);
  92. seeds->key = "seeds";
  93. seeds->required = NO;
  94. seeds->description = _("Name for input raster map with starting seeds");
  95. /* Polygon constraints. */
  96. bounds = G_define_standard_option(G_OPT_R_INPUT);
  97. bounds->key = "bounds";
  98. bounds->required = NO;
  99. bounds->label = _("Name of input bounding/constraining raster map");
  100. bounds->description =
  101. _("Must be integer values, each area will be segmented independent of the others");
  102. outband = G_define_standard_option(G_OPT_R_OUTPUT);
  103. outband->key = "goodness";
  104. outband->required = NO;
  105. outband->description =
  106. _("Name for output goodness of fit estimate map");
  107. diagonal = G_define_flag();
  108. diagonal->key = 'd';
  109. diagonal->description =
  110. _("Use 8 neighbors (3x3 neighborhood) instead of the default 4 neighbors for each pixel");
  111. diagonal->guisection = _("Settings");
  112. weighted = G_define_flag();
  113. weighted->key = 'w';
  114. weighted->description =
  115. _("Weighted input, do not perform the default scaling of input raster maps");
  116. weighted->guisection = _("Settings");
  117. if (G_parser(argc, argv))
  118. exit(EXIT_FAILURE);
  119. /* Check and save parameters */
  120. globals->image_group = group->answer;
  121. if (G_legal_filename(output->answer) == TRUE)
  122. globals->out_name = output->answer;
  123. else
  124. G_fatal_error("Invalid output raster name");
  125. /* Note: this threshold is scaled after we know more at the beginning of create_isegs() */
  126. globals->alpha = atof(threshold->answer);
  127. if (globals->alpha <= 0 || globals->alpha >= 1)
  128. G_fatal_error(_("Threshold should be > 0 and < 1"));
  129. /* segmentation methods: 1 = region growing */
  130. if (strcmp(method->answer, "region_growing") == 0)
  131. globals->method = region_growing;
  132. else if (strcmp(method->answer, "mean_shift") == 0)
  133. globals->method = mean_shift;
  134. else if (strcmp(method->answer, "watershed") == 0)
  135. globals->method = watershed;
  136. else
  137. G_fatal_error(_("Unable to assign segmentation method"));
  138. G_debug(1, "segmentation method: %s", method->answer);
  139. /* distance methods for similarity measurement */
  140. if (strcmp(similarity->answer, "euclidean") == 0)
  141. globals->calculate_similarity = calculate_euclidean_similarity;
  142. else if (strcmp(similarity->answer, "manhattan") == 0)
  143. globals->calculate_similarity = calculate_manhattan_similarity;
  144. else
  145. G_fatal_error(_("Invalid similarity method"));
  146. #ifdef _OR_SHAPE_
  147. /* consider shape */
  148. globals->radio_weight = atof(radio_weight->answer);
  149. if (globals->radio_weight <= 0)
  150. G_fatal_error(_("Option '%s' must be > 0"), radio_weight->key);
  151. if (globals->radio_weight > 1)
  152. G_fatal_error(_("Option '%s' must be <= 1"), radio_weight->key);
  153. globals->smooth_weight = atof(smooth_weight->answer);
  154. if (globals->smooth_weight < 0)
  155. G_fatal_error(_("Option '%s' must be >= 0"), smooth_weight->key);
  156. if (globals->smooth_weight > 1)
  157. G_fatal_error(_("Option '%s' must be <= 1"), smooth_weight->key);
  158. #else
  159. globals->radio_weight = 1;
  160. globals->smooth_weight = 0.5;
  161. #endif
  162. globals->min_segment_size = atoi(min_segment_size->answer);
  163. if (diagonal->answer == FALSE) {
  164. globals->find_neighbors = find_four_neighbors;
  165. globals->nn = 4;
  166. G_debug(1, "four pixel neighborhood");
  167. }
  168. else if (diagonal->answer == TRUE) {
  169. globals->find_neighbors = find_eight_neighbors;
  170. globals->nn = 8;
  171. G_debug(1, "eight (3x3) pixel neighborhood");
  172. }
  173. /* default/0 for performing the scaling
  174. * selected/1 if scaling should be skipped. */
  175. globals->weighted = weighted->answer;
  176. globals->seeds = seeds->answer;
  177. if (globals->seeds) {
  178. if (G_find_raster(globals->seeds, "") == NULL) {
  179. G_fatal_error(_("Seeds raster map not found"));
  180. }
  181. if (Rast_map_type(globals->seeds, "") !=
  182. CELL_TYPE) {
  183. G_fatal_error(_("Seeeds raster map must be CELL type (integers)"));
  184. }
  185. }
  186. if (bounds->answer == NULL) {
  187. globals->bounds_map = NULL;
  188. }
  189. else {
  190. globals->bounds_map = bounds->answer;
  191. if ((globals->bounds_mapset = G_find_raster(globals->bounds_map, "")) == NULL) {
  192. G_fatal_error(_("Segmentation constraint/boundary raster map not found"));
  193. }
  194. if (Rast_map_type(globals->bounds_map, globals->bounds_mapset) !=
  195. CELL_TYPE) {
  196. G_fatal_error(_("Segmentation constraint raster map must be CELL type (integers)"));
  197. }
  198. }
  199. /* other data */
  200. globals->nrows = Rast_window_rows();
  201. globals->ncols = Rast_window_cols();
  202. /* debug help */
  203. if (outband->answer == NULL)
  204. globals->out_band = NULL;
  205. else {
  206. if (G_legal_filename(outband->answer) == TRUE)
  207. globals->out_band = outband->answer;
  208. else
  209. G_fatal_error(_("Invalid output raster name for goodness of fit"));
  210. }
  211. if (endt->answer) {
  212. if (atoi(endt->answer) > 0)
  213. globals->end_t = atoi(endt->answer);
  214. else {
  215. globals->end_t = 100;
  216. G_warning(_("Invalid number of iterations, 100 will be used"));
  217. }
  218. }
  219. else
  220. globals->end_t = 1000;
  221. if (mem->answer && atoi(mem->answer) > 10)
  222. globals->mb = atoi(mem->answer);
  223. else {
  224. globals->mb = 300;
  225. G_warning(_("Invalid number of MB, 300 will be used"));
  226. }
  227. return TRUE;
  228. }