main.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /****************************************************************************
  2. *
  3. * MODULE: i.zc
  4. * AUTHOR(S): David B. Satnik Central Washington University GIS Laboratory
  5. * (original contributor), based on code provided by Bill Hoff
  6. * at University of Illinois
  7. * Markus Neteler <neteler 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: edge detection for imagery using zero crossings method
  13. * COPYRIGHT: (C) 1999-2006 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 <math.h>
  22. #include <grass/gis.h>
  23. #include <grass/raster.h>
  24. #include <grass/gmath.h>
  25. #include <grass/glocale.h>
  26. int main(int argc, char *argv[])
  27. {
  28. /* Global variable & function declarations */
  29. double Thresh;
  30. int NumOrients;
  31. int inputfd, zcfd; /* the input and output file descriptors */
  32. struct Cell_head window;
  33. CELL *cell_row;
  34. float Width;
  35. int i, j; /* Loop control variables */
  36. int or, oc; /* Original dimensions of image */
  37. int rows, cols; /* Smallest powers of 2 >= number of rows & columns */
  38. int size; /* the length of one side */
  39. long totsize; /* the Total number of data points */
  40. double *data[2]; /* Data structure containing real & complex values of FFT */
  41. struct GModule *module;
  42. struct Option *input_map, *output_map, *width, *threshold, *orientations;
  43. G_gisinit(argv[0]);
  44. module = G_define_module();
  45. G_add_keyword(_("imagery"));
  46. G_add_keyword(_("edges"));
  47. module->description =
  48. _("Zero-crossing \"edge detection\" raster "
  49. "function for image processing.");
  50. /* define options */
  51. input_map = G_define_option();
  52. input_map->key = "input";
  53. input_map->type = TYPE_STRING;
  54. input_map->required = YES;
  55. input_map->multiple = NO;
  56. input_map->gisprompt = "old,cell,raster";
  57. input_map->description = _("Name of input raster map");
  58. output_map = G_define_option();
  59. output_map->key = "output";
  60. output_map->type = TYPE_STRING;
  61. output_map->required = YES;
  62. output_map->multiple = NO;
  63. output_map->gisprompt = "new,cell,raster";
  64. output_map->description = _("Zero crossing raster map");
  65. width = G_define_option();
  66. width->key = "width";
  67. width->type = TYPE_INTEGER;
  68. width->required = NO;
  69. width->multiple = NO;
  70. width->description = _("x-y extent of the Gaussian filter");
  71. width->answer = "9";
  72. threshold = G_define_option();
  73. threshold->key = "threshold";
  74. threshold->type = TYPE_DOUBLE;
  75. threshold->required = NO;
  76. threshold->multiple = NO;
  77. threshold->description = _("Sensitivity of Gaussian filter");
  78. threshold->answer = "10";
  79. orientations = G_define_option();
  80. orientations->key = "orientations";
  81. orientations->type = TYPE_INTEGER;
  82. orientations->required = NO;
  83. orientations->multiple = NO;
  84. orientations->description = _("Number of azimuth directions categorized");
  85. orientations->answer = "1";
  86. /* call parser */
  87. if (G_parser(argc, argv))
  88. exit(EXIT_FAILURE);
  89. /* open input cell map */
  90. inputfd = Rast_open_old(input_map->answer, "");
  91. sscanf(threshold->answer, "%1lf", &Thresh);
  92. if (Thresh <= 0.0)
  93. G_fatal_error(_("Threshold less than or equal to zero not allowed"));
  94. Thresh /= 100.0;
  95. sscanf(width->answer, "%f", &Width);
  96. if (Width <= 0.0)
  97. G_fatal_error(_("Width less than or equal to zero not allowed"));
  98. sscanf(orientations->answer, "%d", &NumOrients);
  99. if (NumOrients < 1)
  100. G_fatal_error(_("Fewer than 1 orientation classes not allowed"));
  101. /* get the current window for later */
  102. G_get_set_window(&window);
  103. /* get the rows and columns in the current window */
  104. or = Rast_window_rows();
  105. oc = Rast_window_cols();
  106. rows = G_math_max_pow2((long)or);
  107. cols = G_math_max_pow2((long)oc);
  108. size = (rows > cols) ? rows : cols;
  109. totsize = size * size;
  110. G_message(_("Power 2 values : %d rows %d columns"), rows, cols);
  111. /* Allocate appropriate memory for the structure containing
  112. the real and complex components of the FFT. DATA[0] will
  113. contain the real, and DATA[1] the complex component.
  114. */
  115. data[0] = (double *)G_malloc(totsize * sizeof(double));
  116. data[1] = (double *)G_malloc(totsize * sizeof(double));
  117. /* Initialize real & complex components to zero */
  118. G_message(_("Initializing data..."));
  119. for (i = 0; i < (totsize); i++) {
  120. *(data[0] + i) = 0.0;
  121. *(data[1] + i) = 0.0;
  122. }
  123. /* allocate the space for one row of cell map data */
  124. cell_row = Rast_allocate_c_buf();
  125. /* Read in cell map values */
  126. G_message(_("Reading raster map..."));
  127. for (i = 0; i < or; i++) {
  128. Rast_get_c_row(inputfd, cell_row, i);
  129. for (j = 0; j < oc; j++)
  130. *(data[0] + (i * size) + j) = (double)cell_row[j];
  131. }
  132. /* close input cell map and release the row buffer */
  133. Rast_close(inputfd);
  134. G_free(cell_row);
  135. /* take the del**2g of image */
  136. del2g(data, size, Width);
  137. /* find the zero crossings: Here are several notes -
  138. 1) this routine only uses the real values
  139. 2) it places the zero crossings in the imaginary array */
  140. G_math_findzc(data[0], size, data[1], Thresh, NumOrients);
  141. /* open the output cell maps and allocate cell row buffers */
  142. G_message(_("Writing transformed data to file..."));
  143. zcfd = Rast_open_c_new(output_map->answer);
  144. cell_row = Rast_allocate_c_buf();
  145. /* Write out result to a new cell map */
  146. for (i = 0; i < or; i++) {
  147. for (j = 0; j < oc; j++) {
  148. *(cell_row + j) = (CELL) (*(data[1] + i * cols + j));
  149. }
  150. Rast_put_row(zcfd, cell_row, CELL_TYPE);
  151. }
  152. Rast_close(zcfd);
  153. G_free(cell_row);
  154. /* Release memory resources */
  155. for (i = 0; i < 2; i++)
  156. G_free(data[i]);
  157. G_done_msg(_("Transform successful"));
  158. exit(EXIT_SUCCESS);
  159. }