main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /**************************************************************
  2. *
  3. * MODULE: v.lidar.edgedetection
  4. *
  5. * AUTHOR(S): Original version in GRASS 5.4 (s.edgedetection):
  6. * Maria Antonia Brovelli, Massimiliano Cannata,
  7. * Ulisse Longoni and Mirko Reguzzoni
  8. *
  9. * Update for GRASS 6.X and improvements:
  10. * Roberto Antolin and Gonzalo Moreno
  11. *
  12. * PURPOSE: Detection of object's edges on a LIDAR data set
  13. *
  14. * COPYRIGHT: (C) 2006 by Politecnico di Milano -
  15. * Polo Regionale di Como
  16. *
  17. * This program is free software under the
  18. * GNU General Public License (>=v2).
  19. * Read the file COPYING that comes with GRASS
  20. * for details.
  21. *
  22. **************************************************************/
  23. /*INCLUDES*/
  24. #include <grass/config.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <math.h>
  28. #include "edgedetection.h"
  29. int nsply, nsplx, line_out_counter;
  30. double stepN, stepE;
  31. /**************************************************************************************
  32. **************************************************************************************/
  33. int main(int argc, char *argv[])
  34. {
  35. /* Variables' declarations */
  36. int nsplx_adj, nsply_adj;
  37. int nsubregion_col, nsubregion_row, subregion = 0, nsubregions = 0;
  38. double N_extension, E_extension, edgeE, edgeN;
  39. int dim_vect, nparameters, BW, npoints;
  40. double lambda_B, lambda_F, grad_H, grad_L, alpha, mean;
  41. const char *dvr, *db, *mapset;
  42. char table_interpolation[GNAME_MAX], table_name[GNAME_MAX];
  43. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  44. int last_row, last_column, flag_auxiliar = FALSE;
  45. int *lineVect;
  46. double *TN, *Q, *parVect_bilin, *parVect_bicub; /* Interpolating and least-square vectors */
  47. double **N, **obsVect; /* Interpolation and least-square matrix */
  48. /* Structs' declarations */
  49. struct Map_info In, Out;
  50. struct Option *in_opt, *out_opt, *stepE_opt, *stepN_opt,
  51. *lambdaF_opt, *lambdaB_opt, *gradH_opt, *gradL_opt, *alfa_opt;
  52. struct Flag *spline_step_flag;
  53. struct GModule *module;
  54. struct Cell_head elaboration_reg, original_reg;
  55. struct Reg_dimens dims;
  56. struct bound_box general_box, overlap_box;
  57. struct Point *observ;
  58. dbDriver *driver;
  59. /*------------------------------------------------------------------------------------------*/
  60. /* Options' declaration */
  61. module = G_define_module();
  62. G_add_keyword(_("vector"));
  63. G_add_keyword(_("LIDAR"));
  64. G_add_keyword(_("edges"));
  65. module->description =
  66. _("Detects the object's edges from a LIDAR data set.");
  67. spline_step_flag = G_define_flag();
  68. spline_step_flag->key = 'e';
  69. spline_step_flag->label = _("Estimate point density and distance");
  70. spline_step_flag->description =
  71. _("Estimate point density and distance for the input vector points within the current region extends and quit");
  72. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  73. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  74. stepE_opt = G_define_option();
  75. stepE_opt->key = "see";
  76. stepE_opt->type = TYPE_DOUBLE;
  77. stepE_opt->required = NO;
  78. stepE_opt->answer = "4";
  79. stepE_opt->description =
  80. _("Interpolation spline step value in east direction");
  81. stepE_opt->guisection = _("Settings");
  82. stepN_opt = G_define_option();
  83. stepN_opt->key = "sen";
  84. stepN_opt->type = TYPE_DOUBLE;
  85. stepN_opt->required = NO;
  86. stepN_opt->answer = "4";
  87. stepN_opt->description =
  88. _("Interpolation spline step value in north direction");
  89. stepN_opt->guisection = _("Settings");
  90. lambdaB_opt = G_define_option();
  91. lambdaB_opt->key = "lambda_g";
  92. lambdaB_opt->type = TYPE_DOUBLE;
  93. lambdaB_opt->required = NO;
  94. lambdaB_opt->description =
  95. _("Regularization weight in gradient evaluation");
  96. lambdaB_opt->answer = "0.01";
  97. lambdaB_opt->guisection = _("Settings");
  98. gradH_opt = G_define_option();
  99. gradH_opt->key = "tgh";
  100. gradH_opt->type = TYPE_DOUBLE;
  101. gradH_opt->required = NO;
  102. gradH_opt->description =
  103. _("High gradient threshold for edge classification");
  104. gradH_opt->answer = "6";
  105. gradH_opt->guisection = _("Settings");
  106. gradL_opt = G_define_option();
  107. gradL_opt->key = "tgl";
  108. gradL_opt->type = TYPE_DOUBLE;
  109. gradL_opt->required = NO;
  110. gradL_opt->description =
  111. _("Low gradient threshold for edge classification");
  112. gradL_opt->answer = "3";
  113. gradL_opt->guisection = _("Settings");
  114. alfa_opt = G_define_option();
  115. alfa_opt->key = "theta_g";
  116. alfa_opt->type = TYPE_DOUBLE;
  117. alfa_opt->required = NO;
  118. alfa_opt->description = _("Angle range for same direction detection");
  119. alfa_opt->answer = "0.26";
  120. alfa_opt->guisection = _("Settings");
  121. lambdaF_opt = G_define_option();
  122. lambdaF_opt->key = "lambda_r";
  123. lambdaF_opt->type = TYPE_DOUBLE;
  124. lambdaF_opt->required = NO;
  125. lambdaF_opt->description =
  126. _("Regularization weight in residual evaluation");
  127. lambdaF_opt->answer = "2";
  128. lambdaF_opt->guisection = _("Settings");
  129. /* Parsing */
  130. G_gisinit(argv[0]);
  131. if (G_parser(argc, argv))
  132. exit(EXIT_FAILURE);
  133. line_out_counter = 1;
  134. stepN = atof(stepN_opt->answer);
  135. stepE = atof(stepE_opt->answer);
  136. lambda_F = atof(lambdaF_opt->answer);
  137. lambda_B = atof(lambdaB_opt->answer);
  138. grad_H = atof(gradH_opt->answer);
  139. grad_L = atof(gradL_opt->answer);
  140. alpha = atof(alfa_opt->answer);
  141. grad_L = grad_L * grad_L;
  142. grad_H = grad_H * grad_H;
  143. if (!(db = G__getenv2("DB_DATABASE", G_VAR_MAPSET)))
  144. G_fatal_error(_("Unable to read name of database"));
  145. if (!(dvr = G__getenv2("DB_DRIVER", G_VAR_MAPSET)))
  146. G_fatal_error(_("Unable to read name of driver"));
  147. /* Setting auxiliar table's name */
  148. if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) {
  149. sprintf(table_name, "%s_aux", xname);
  150. sprintf(table_interpolation, "%s_edge_Interpolation", xname);
  151. }
  152. else {
  153. sprintf(table_name, "%s_aux", out_opt->answer);
  154. sprintf(table_interpolation, "%s_edge_Interpolation", out_opt->answer);
  155. }
  156. /* Something went wrong in a previous v.lidar.edgedetection execution */
  157. if (db_table_exists(dvr, db, table_name)) {
  158. /* Start driver and open db */
  159. driver = db_start_driver_open_database(dvr, db);
  160. if (driver == NULL)
  161. G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
  162. dvr);
  163. if (P_Drop_Aux_Table(driver, table_name) != DB_OK)
  164. G_fatal_error(_("Old auxiliar table could not be dropped"));
  165. db_close_database_shutdown_driver(driver);
  166. }
  167. /* Something went wrong in a previous v.lidar.edgedetection execution */
  168. if (db_table_exists(dvr, db, table_interpolation)) {
  169. /* Start driver and open db */
  170. driver = db_start_driver_open_database(dvr, db);
  171. if (driver == NULL)
  172. G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
  173. dvr);
  174. if (P_Drop_Aux_Table(driver, table_interpolation) != DB_OK)
  175. G_fatal_error(_("Old auxiliar table could not be dropped"));
  176. db_close_database_shutdown_driver(driver);
  177. }
  178. /* Checking vector names */
  179. Vect_check_input_output_name(in_opt->answer, out_opt->answer,
  180. GV_FATAL_EXIT);
  181. if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) {
  182. G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);
  183. }
  184. Vect_set_open_level(1);
  185. /* Open input vector */
  186. if (1 > Vect_open_old(&In, in_opt->answer, mapset))
  187. G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer);
  188. /* Input vector must be 3D */
  189. if (!Vect_is_3d(&In))
  190. G_fatal_error(_("Input vector map <%s> is not 3D!"), in_opt->answer);
  191. /* Estimate point density and mean distance for current region */
  192. if (spline_step_flag->answer) {
  193. double dens, dist;
  194. if (P_estimate_splinestep(&In, &dens, &dist) == 0) {
  195. G_message("Estimated point density: %.4g", dens);
  196. G_message("Estimated mean distance between points: %.4g", dist);
  197. }
  198. else
  199. G_warning(_("No points in current region!"));
  200. Vect_close(&In);
  201. exit(EXIT_SUCCESS);
  202. }
  203. /* Open output vector */
  204. if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z))
  205. G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
  206. /* Copy vector Head File */
  207. Vect_copy_head_data(&In, &Out);
  208. Vect_hist_copy(&In, &Out);
  209. Vect_hist_command(&Out);
  210. /* Start driver and open db */
  211. driver = db_start_driver_open_database(dvr, db);
  212. if (driver == NULL)
  213. G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
  214. dvr);
  215. /* Create auxiliar and interpolation table */
  216. if ((flag_auxiliar = P_Create_Aux4_Table(driver, table_name)) == FALSE)
  217. G_fatal_error(_("It was impossible to create <%s>."), table_name);
  218. if (P_Create_Aux2_Table(driver, table_interpolation) == FALSE)
  219. G_fatal_error(_("It was impossible to create <%s> interpolation table in database."),
  220. out_opt->answer);
  221. db_create_index2(driver, table_name, "ID");
  222. db_create_index2(driver, table_interpolation, "ID");
  223. /* sqlite likes that */
  224. db_close_database_shutdown_driver(driver);
  225. driver = db_start_driver_open_database(dvr, db);
  226. /* Setting regions and boxes */
  227. G_get_set_window(&original_reg);
  228. G_get_set_window(&elaboration_reg);
  229. Vect_region_box(&elaboration_reg, &overlap_box);
  230. Vect_region_box(&elaboration_reg, &general_box);
  231. /*------------------------------------------------------------------
  232. | Subdividing and working with tiles:
  233. | Each original region will be divided into several subregions.
  234. | Each one will be overlaped by its neighbouring subregions.
  235. | The overlapping is calculated as a fixed OVERLAP_SIZE times
  236. | the largest spline step plus 2 * edge
  237. ----------------------------------------------------------------*/
  238. /* Fixing parameters of the elaboration region */
  239. P_zero_dim(&dims);
  240. nsplx_adj = NSPLX_MAX;
  241. nsply_adj = NSPLY_MAX;
  242. if (stepN > stepE)
  243. dims.overlap = OVERLAP_SIZE * stepN;
  244. else
  245. dims.overlap = OVERLAP_SIZE * stepE;
  246. P_get_edge(P_BICUBIC, &dims, stepE, stepN);
  247. P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj);
  248. G_verbose_message(_("adjusted EW splines %d"), nsplx_adj);
  249. G_verbose_message(_("adjusted NS splines %d"), nsply_adj);
  250. /* calculate number of subregions */
  251. edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v;
  252. edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h;
  253. N_extension = original_reg.north - original_reg.south;
  254. E_extension = original_reg.east - original_reg.west;
  255. nsubregion_col = ceil(E_extension / edgeE) + 0.5;
  256. nsubregion_row = ceil(N_extension / edgeN) + 0.5;
  257. if (nsubregion_col < 0)
  258. nsubregion_col = 0;
  259. if (nsubregion_row < 0)
  260. nsubregion_row = 0;
  261. nsubregions = nsubregion_row * nsubregion_col;
  262. elaboration_reg.south = original_reg.north;
  263. last_row = FALSE;
  264. while (last_row == FALSE) { /* For each row */
  265. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  266. GENERAL_ROW);
  267. if (elaboration_reg.north > original_reg.north) { /* First row */
  268. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  269. FIRST_ROW);
  270. }
  271. if (elaboration_reg.south <= original_reg.south) { /* Last row */
  272. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  273. LAST_ROW);
  274. last_row = TRUE;
  275. }
  276. nsply =
  277. ceil((elaboration_reg.north - elaboration_reg.south) / stepN) +
  278. 0.5;
  279. /*
  280. if (nsply > NSPLY_MAX) {
  281. nsply = NSPLY_MAX;
  282. }
  283. */
  284. G_debug(1, "nsply = %d", nsply);
  285. elaboration_reg.east = original_reg.west;
  286. last_column = FALSE;
  287. while (last_column == FALSE) { /* For each column */
  288. subregion++;
  289. if (nsubregions > 1)
  290. G_message(_("subregion %d of %d"), subregion, nsubregions);
  291. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  292. GENERAL_COLUMN);
  293. if (elaboration_reg.west < original_reg.west) { /* First column */
  294. P_set_regions(&elaboration_reg, &general_box, &overlap_box,
  295. dims, FIRST_COLUMN);
  296. }
  297. if (elaboration_reg.east >= original_reg.east) { /* Last column */
  298. P_set_regions(&elaboration_reg, &general_box, &overlap_box,
  299. dims, LAST_COLUMN);
  300. last_column = TRUE;
  301. }
  302. nsplx =
  303. ceil((elaboration_reg.east - elaboration_reg.west) / stepE) +
  304. 0.5;
  305. /*
  306. if (nsplx > NSPLX_MAX) {
  307. nsplx = NSPLX_MAX;
  308. }
  309. */
  310. G_debug(1, "nsplx = %d", nsplx);
  311. /*Setting the active region */
  312. dim_vect = nsplx * nsply;
  313. G_debug(1, "read vector region map");
  314. observ =
  315. P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints,
  316. dim_vect, 1);
  317. if (npoints > 0) { /* If there is any point falling into elaboration_reg... */
  318. int i, tn;
  319. nparameters = nsplx * nsply;
  320. /* Mean's calculation */
  321. mean = P_Mean_Calc(&elaboration_reg, observ, npoints);
  322. /* Least Squares system */
  323. G_debug(1, _("Allocating memory for bilinear interpolation"));
  324. BW = P_get_BandWidth(P_BILINEAR, nsply); /* Bilinear interpolation */
  325. N = G_alloc_matrix(nparameters, BW); /* Normal matrix */
  326. TN = G_alloc_vector(nparameters); /* vector */
  327. parVect_bilin = G_alloc_vector(nparameters); /* Bilinear parameters vector */
  328. obsVect = G_alloc_matrix(npoints + 1, 3); /* Observation vector */
  329. Q = G_alloc_vector(npoints + 1); /* "a priori" var-cov matrix */
  330. lineVect = G_alloc_ivector(npoints + 1);
  331. /* Setting obsVect vector & Q matrix */
  332. for (i = 0; i < npoints; i++) {
  333. obsVect[i][0] = observ[i].coordX;
  334. obsVect[i][1] = observ[i].coordY;
  335. obsVect[i][2] = observ[i].coordZ - mean;
  336. lineVect[i] = observ[i].lineID;
  337. Q[i] = 1; /* Q=I */
  338. }
  339. G_free(observ);
  340. G_verbose_message(_("Bilinear interpolation"));
  341. normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx,
  342. nsply, elaboration_reg.west,
  343. elaboration_reg.south, npoints, nparameters,
  344. BW);
  345. nCorrectGrad(N, lambda_B, nsplx, nsply, stepE, stepN);
  346. G_math_solver_cholesky_sband(N, parVect_bilin, TN, nparameters, BW);
  347. G_free_matrix(N);
  348. for (tn = 0; tn < nparameters; tn++)
  349. TN[tn] = 0;
  350. G_debug(1, _("Allocating memory for bicubic interpolation"));
  351. BW = P_get_BandWidth(P_BICUBIC, nsply);
  352. N = G_alloc_matrix(nparameters, BW); /* Normal matrix */
  353. parVect_bicub = G_alloc_vector(nparameters); /* Bicubic parameters vector */
  354. G_verbose_message(_("Bicubic interpolation"));
  355. normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx,
  356. nsply, elaboration_reg.west,
  357. elaboration_reg.south, npoints, nparameters,
  358. BW);
  359. nCorrectLapl(N, lambda_F, nsplx, nsply, stepE, stepN);
  360. G_math_solver_cholesky_sband(N, parVect_bicub, TN, nparameters, BW);
  361. G_free_matrix(N);
  362. G_free_vector(TN);
  363. G_free_vector(Q);
  364. G_verbose_message(_("Point classification"));
  365. classification(&Out, elaboration_reg, general_box,
  366. overlap_box, obsVect, parVect_bilin,
  367. parVect_bicub, mean, alpha, grad_H, grad_L,
  368. dims.overlap, lineVect, npoints, driver,
  369. table_interpolation, table_name);
  370. G_free_vector(parVect_bilin);
  371. G_free_vector(parVect_bicub);
  372. G_free_matrix(obsVect);
  373. G_free_ivector(lineVect);
  374. } /* IF */
  375. else {
  376. G_free(observ);
  377. G_warning(_("No data within this subregion. "
  378. "Consider changing the spline step."));
  379. }
  380. } /*! END WHILE; last_column = TRUE */
  381. } /*! END WHILE; last_row = TRUE */
  382. /* Dropping auxiliar table */
  383. if (npoints > 0) {
  384. G_debug(1, _("Dropping <%s>"), table_name);
  385. if (P_Drop_Aux_Table(driver, table_name) != DB_OK)
  386. G_warning(_("Auxiliar table could not be dropped"));
  387. }
  388. db_close_database_shutdown_driver(driver);
  389. Vect_close(&In);
  390. Vect_map_add_dblink(&Out, F_INTERPOLATION, NULL, table_interpolation,
  391. "id", db, dvr);
  392. Vect_close(&Out);
  393. G_done_msg(" ");
  394. exit(EXIT_SUCCESS);
  395. } /*!END MAIN */