1 // ----------------------------------------------------------------------------
2 // -                        Open3D: www.open3d.org                            -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #include <iostream>
28 #include <memory>
29 
30 #include <Eigen/Dense>
31 #include <Core/Core.h>
32 #include <IO/IO.h>
33 #include <Visualization/Visualization.h>
34 
ReadLogFile(const std::string & filename,std::vector<std::tuple<int,int,int>> & metadata,std::vector<Eigen::Matrix4d> & transformations)35 bool ReadLogFile(const std::string &filename,
36         std::vector<std::tuple<int, int, int>> &metadata,
37         std::vector<Eigen::Matrix4d> &transformations)
38 {
39     using namespace three;
40     metadata.clear();
41     transformations.clear();
42     FILE * f = fopen(filename.c_str(), "r");
43     if (f == NULL) {
44         PrintWarning("Read LOG failed: unable to open file.\n");
45         return false;
46     }
47     char line_buffer[DEFAULT_IO_BUFFER_SIZE];
48     int i, j, k;
49     Eigen::Matrix4d trans;
50     while (fgets(line_buffer, DEFAULT_IO_BUFFER_SIZE, f)) {
51         if (strlen(line_buffer) > 0 && line_buffer[0] != '#') {
52             if (sscanf(line_buffer, "%d %d %d", &i, &j, &k) != 3) {
53                 PrintWarning("Read LOG failed: unrecognized format.\n");
54                 return false;
55             }
56             if (fgets(line_buffer, DEFAULT_IO_BUFFER_SIZE, f) == 0) {
57                 PrintWarning("Read LOG failed: unrecognized format.\n");
58                 return false;
59             } else {
60                 sscanf(line_buffer, "%lf %lf %lf %lf", &trans(0,0), &trans(0,1),
61                         &trans(0,2), &trans(0,3));
62             }
63             if (fgets(line_buffer, DEFAULT_IO_BUFFER_SIZE, f) == 0) {
64                 PrintWarning("Read LOG failed: unrecognized format.\n");
65                 return false;
66             } else {
67                 sscanf(line_buffer, "%lf %lf %lf %lf", &trans(1,0), &trans(1,1),
68                         &trans(1,2), &trans(1,3));
69             }
70             if (fgets(line_buffer, DEFAULT_IO_BUFFER_SIZE, f) == 0) {
71                 PrintWarning("Read LOG failed: unrecognized format.\n");
72                 return false;
73             } else {
74                 sscanf(line_buffer, "%lf %lf %lf %lf", &trans(2,0), &trans(2,1),
75                         &trans(2,2), &trans(2,3));
76             }
77             if (fgets(line_buffer, DEFAULT_IO_BUFFER_SIZE, f) == 0) {
78                 PrintWarning("Read LOG failed: unrecognized format.\n");
79                 return false;
80             } else {
81                 sscanf(line_buffer, "%lf %lf %lf %lf", &trans(3,0), &trans(3,1),
82                         &trans(3,2), &trans(3,3));
83             }
84             metadata.push_back(std::make_tuple(i, j, k));
85             transformations.push_back(trans);
86         }
87     }
88     fclose(f);
89     return true;
90 }
91 
PrintHelp()92 void PrintHelp()
93 {
94     printf("Open3D %s\n", OPEN3D_VERSION);
95     printf("\n");
96     printf("Usage:\n");
97     printf("    > ViewPCDMatch [options]\n");
98     printf("      View pairwise matching result of point clouds.\n");
99     printf("\n");
100     printf("Basic options:\n");
101     printf("    --help, -h                : Print help information.\n");
102     printf("    --log file                : A log file of the pairwise matching results. Must have.\n");
103     printf("    --dir directory           : The directory storing all pcd files. By default it is the parent directory of the log file + pcd/.\n");
104     printf("    --verbose n               : Set verbose level (0-4). Default: 2.\n");
105 }
106 
main(int argc,char * argv[])107 int main(int argc, char *argv[])
108 {
109     using namespace three;
110 
111     if (argc <= 1 || ProgramOptionExists(argc, argv, "--help") ||
112             ProgramOptionExists(argc, argv, "-h")) {
113         PrintHelp();
114         return 0;
115     }
116     const int NUM_OF_COLOR_PALETTE = 5;
117     Eigen::Vector3d color_palette[NUM_OF_COLOR_PALETTE] = {
118         Eigen::Vector3d(255, 180, 0) / 255.0,
119         Eigen::Vector3d(0, 166, 237) / 255.0,
120         Eigen::Vector3d(246, 81, 29) / 255.0,
121         Eigen::Vector3d(127, 184, 0) / 255.0,
122         Eigen::Vector3d(13, 44, 84) / 255.0,
123     };
124 
125     int verbose = GetProgramOptionAsInt(argc, argv, "--verbose", 2);
126     SetVerbosityLevel((VerbosityLevel)verbose);
127     std::string log_filename = GetProgramOptionAsString(argc, argv, "--log");
128     std::string pcd_dirname = GetProgramOptionAsString(argc, argv, "--dir");
129     if (pcd_dirname.empty()) {
130         pcd_dirname = filesystem::GetFileParentDirectory(log_filename) +
131                 "pcds/";
132     }
133 
134     std::vector<std::tuple<int, int, int>> metadata;
135     std::vector<Eigen::Matrix4d> transformations;
136     ReadLogFile(log_filename, metadata, transformations);
137 
138     for (auto k = 0; k < metadata.size(); k++) {
139         auto i = std::get<0>(metadata[k]), j = std::get<1>(metadata[k]);
140         PrintInfo("Showing matched point cloud #%d and #%d.\n", i, j);
141         auto pcd_target = CreatePointCloudFromFile(pcd_dirname + "cloud_bin_" +
142                 std::to_string(i) + ".pcd");
143         pcd_target->colors_.clear();
144         pcd_target->colors_.resize(pcd_target->points_.size(),
145                 color_palette[0]);
146         auto pcd_source = CreatePointCloudFromFile(pcd_dirname + "cloud_bin_" +
147                 std::to_string(j) + ".pcd");
148         pcd_source->colors_.clear();
149         pcd_source->colors_.resize(pcd_source->points_.size(),
150                 color_palette[1]);
151         pcd_source->Transform(transformations[k]);
152         DrawGeometriesWithCustomAnimation({pcd_target, pcd_source},
153                 "ViewPCDMatch", 1600, 900);
154     }
155     return 1;
156 }
157