/demos/pmatch-gui/src/main.cc

https://bitbucket.org/tetonedge/libsrvf · C++ · 220 lines · 170 code · 32 blank · 18 comment · 22 complexity · 3c0179a173f5ff74be8026317c78c2c9 MD5 · raw file

  1. /*
  2. * LibSRVF - a shape analysis library using the square root velocity framework.
  3. *
  4. * Copyright (C) 2012 FSU Statistical Shape Analysis and Modeling Group
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>
  18. */
  19. #include "matchview.h"
  20. #include "ui.h"
  21. #include <srvf/partialmatch.h>
  22. #include <srvf/paretoset.h>
  23. #include <srvf/matrix.h>
  24. #include <srvf/plf.h>
  25. #include <srvf/srvf.h>
  26. #include <srvf/qmap.h>
  27. #include <srvf/fileio.h>
  28. #include <FL/Fl.H>
  29. #include <iostream>
  30. #include <fstream>
  31. #include <cstdlib>
  32. #include <unistd.h>
  33. #define DEFAULT_GRID_WIDTH 0
  34. #define DEFAULT_GRID_HEIGHT 0
  35. static void do_usage(const char *progname)
  36. {
  37. std::cout << "USAGE: " << progname << " [OPTIONS] file1 file2" << std::endl;
  38. std::cout << "where" << std::endl;
  39. std::cout << " file1 contains samples for the first curve" << std::endl;
  40. std::cout << " file2 contains samples for the second curve" << std::endl;
  41. std::cout << "Recognized options are:" << std::endl;
  42. std::cout << " -W n\t\tuse grid width n" << std::endl;
  43. std::cout << " -H n\t\tuse grid height n" << std::endl;
  44. std::cout << " -r\t\toptimize over rotations" << std::endl;
  45. std::cout << " -p\t\tsample point matrices in file1 and file2 "
  46. "are in point-per-column ordering" << std::endl;
  47. std::cout << " -o outfile\twrite matches to outfile" << std::endl;
  48. std::cout << " -h\t\tshow this message" << std::endl;
  49. }
  50. int main( int argc, char **argv ){
  51. size_t grid_width = DEFAULT_GRID_WIDTH;
  52. size_t grid_height = DEFAULT_GRID_HEIGHT;
  53. bool do_rotations = false;
  54. double salukwadze_weight = 1.0;
  55. const char *output_filename = "matches.mat";
  56. srvf::Pointset::PackingMethod packing = srvf::Pointset::POINT_PER_ROW;
  57. int opt;
  58. while( (opt=getopt(argc, argv, "W:H:rw:po:h")) != -1 ){
  59. switch( opt ){
  60. case 'W':
  61. grid_width = atoi(optarg);
  62. break;
  63. case 'H':
  64. grid_height = atoi(optarg);
  65. break;
  66. case 'r':
  67. do_rotations = true;
  68. break;
  69. case 'w': // shape distance weight for Salukwadze distance
  70. salukwadze_weight = atof(optarg);
  71. break;
  72. case 'p': // sample point matrix = point per column
  73. packing = srvf::Pointset::POINT_PER_COLUMN;
  74. break;
  75. case 'o':
  76. output_filename = optarg;
  77. break;
  78. case 'h':
  79. do_usage(argv[0]);
  80. return 0;
  81. case '?':
  82. do_usage(argv[0]);
  83. return -1;
  84. }
  85. }
  86. if (argc - optind != 2) {
  87. do_usage(argv[0]);
  88. return -1;
  89. }
  90. std::ifstream ifs1(argv[optind]);
  91. std::ifstream ifs2(argv[optind+1]);
  92. std::vector<srvf::Matrix> F1data = srvf::io::load_csv ( ifs1, ' ', '\n' );
  93. std::vector<srvf::Matrix> F2data = srvf::io::load_csv ( ifs2, ' ', '\n' );
  94. ifs1.close();
  95. ifs2.close();
  96. if (F1data.size() == 0)
  97. {
  98. std::cerr << "Failed to load matrix from " << argv[optind]
  99. << "; exiting." << std::endl;
  100. return -1;
  101. }
  102. if (F2data.size() == 0)
  103. {
  104. std::cerr << "Failed to load matrix from " << argv[optind+1]
  105. << "; exiting." << std::endl;
  106. return -1;
  107. }
  108. srvf::Pointset F1samps(F1data[0], packing);
  109. srvf::Pointset F2samps(F2data[0], packing);
  110. srvf::Plf F1(F1samps);
  111. srvf::Plf F2(F2samps);
  112. std::cout << "F1 has " << F1.ncp() << " changepoints" << std::endl;
  113. std::cout << "F2 has " << F2.ncp() << " changepoints" << std::endl;
  114. if (F1.dim() != 2 && F1.dim() != 3)
  115. {
  116. std::cerr << "Invalid dimension: curves must have dimension 2 or 3."
  117. << std::endl;
  118. return -1;
  119. }
  120. if (F1.dim() != F2.dim())
  121. {
  122. std::cerr << "F1 and F2 have different dimensions." << std::endl;
  123. return -1;
  124. }
  125. double L1 = F1.arc_length();
  126. double L2 = F2.arc_length();
  127. double L = std::min(L1, L2);
  128. F1.scale( 1.0 / L );
  129. F2.scale( 1.0 / L );
  130. srvf::Srvf Q1 = srvf::plf_to_srvf(F1);
  131. srvf::Srvf Q2 = srvf::plf_to_srvf(F2);
  132. srvf::pmatch::ParetoSet S = srvf::pmatch::find_matches (
  133. Q1, Q2, do_rotations, grid_width, grid_height);
  134. std::vector<double> reg_errs = S.regression_errors();
  135. for (size_t i=0; i<reg_errs.size(); ++i)
  136. {
  137. if (S[i].empty()) continue;
  138. std::cout << S[i][0].length() << " "
  139. << reg_errs[i] << std::endl;
  140. }
  141. std::ofstream ofs(output_filename);
  142. ofs << "# srvf_pmatch output" << std::endl;
  143. ofs << "# File 1: " << argv[optind] << std::endl;
  144. ofs << "# File 2: " << argv[optind+1] << std::endl;
  145. ofs << "# Salukwadze dist: "
  146. << S.salukwadze_dist(salukwadze_weight)
  147. << std::endl << std::endl;
  148. ofs << "# name: salukwadze_dist" << std::endl;
  149. ofs << "# type: matrix" << std::endl;
  150. ofs << "# rows: 1" << std::endl;
  151. ofs << "# columns: 1" << std::endl;
  152. ofs << S.salukwadze_dist(salukwadze_weight)
  153. << std::endl << std::endl;
  154. ofs << "# name: pareto_set" << std::endl;
  155. ofs << "# type: matrix" << std::endl;
  156. ofs << "# rows: " << S.total_size() << std::endl;
  157. ofs << "# columns: 5" << std::endl;
  158. for (size_t i=0; i<S.nbuckets(); ++i)
  159. {
  160. for (size_t j=0; j<S[i].size(); ++j)
  161. {
  162. ofs << S[i][j].a << " " << S[i][j].b << " "
  163. << S[i][j].c << " " << S[i][j].d << " "
  164. << S[i][j].dist << std::endl;
  165. }
  166. }
  167. ofs.close();
  168. srvf::plot::Plot *plot = NULL;
  169. if (F1.dim() == 2)
  170. plot = new srvf::plot::Plot2D();
  171. else // dim = 3
  172. plot = new srvf::plot::Plot3D();
  173. plot->insert(F1, srvf::plot::Color(0.0, 0.0, 1.0), 2.0);
  174. plot->insert(F2, srvf::plot::Color(1.0, 0.0, 0.0), 2.0);
  175. UserInterface ui;
  176. Fl_Window *win = ui.make_window();
  177. ui.match_view->do_rotations(do_rotations);
  178. ui.match_view->set_plot(plot);
  179. ui.match_view->set_matches(S);
  180. ui.slider_match_length->range(0.0, (double)(S.nbuckets()-1));
  181. ui.slider_match_length->step(1.0);
  182. ui.slider_match_length->value((double)(S.nbuckets()-1));
  183. ui.set_match();
  184. win->show();
  185. Fl::run();
  186. delete plot;
  187. return 0;
  188. }