forked from rmsalinas/DBow3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdemo_general.cpp
202 lines (154 loc) · 6.33 KB
/
demo_general.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
* Date: 2016
* Author: Rafael Muñoz Salinas
* Description: demo application of DBoW3
* License: see the LICENSE.txt file
*/
#include <iostream>
#include <vector>
// DBoW3
#include "DBoW3.h"
// OpenCV
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#ifdef USE_CONTRIB
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/xfeatures2d.hpp>
#endif
#include "DescManip.h"
using namespace DBoW3;
using namespace std;
//command line parser
class CmdLineParser{int argc; char **argv; public: CmdLineParser(int _argc,char **_argv):argc(_argc),argv(_argv){} bool operator[] ( string param ) {int idx=-1; for ( int i=0; i<argc && idx==-1; i++ ) if ( string ( argv[i] ) ==param ) idx=i; return ( idx!=-1 ) ; } string operator()(string param,string defvalue="-1"){int idx=-1; for ( int i=0; i<argc && idx==-1; i++ ) if ( string ( argv[i] ) ==param ) idx=i; if ( idx==-1 ) return defvalue; else return ( argv[ idx+1] ); }};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// extended surf gives 128-dimensional vectors
const bool EXTENDED_SURF = false;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void wait()
{
cout << endl << "Press enter to continue" << endl;
getchar();
}
vector<string> readImagePaths(int argc,char **argv,int start){
vector<string> paths;
for(int i=start;i<argc;i++) paths.push_back(argv[i]);
return paths;
}
vector< cv::Mat > loadFeatures( std::vector<string> path_to_images,string descriptor="") throw (std::exception){
//select detector
cv::Ptr<cv::Feature2D> fdetector;
if (descriptor=="orb") fdetector=cv::ORB::create();
else if (descriptor=="brisk") fdetector=cv::BRISK::create();
#ifdef OPENCV_VERSION_3
else if (descriptor=="akaze") fdetector=cv::AKAZE::create();
#endif
#ifdef USE_CONTRIB
else if(descriptor=="surf" ) fdetector=cv::xfeatures2d::SURF::create(400, 4, 2, EXTENDED_SURF);
#endif
else throw std::runtime_error("Invalid descriptor");
assert(!descriptor.empty());
vector<cv::Mat> features;
cout << "Extracting features..." << endl;
for(size_t i = 0; i < path_to_images.size(); ++i)
{
vector<cv::KeyPoint> keypoints;
cv::Mat descriptors;
cout<<"reading image: "<<path_to_images[i]<<endl;
cv::Mat image = cv::imread(path_to_images[i], 0);
if(image.empty())throw std::runtime_error("Could not open image"+path_to_images[i]);
cout<<"extracting features"<<endl;
fdetector->detectAndCompute(image, cv::Mat(), keypoints, descriptors);
features.push_back(descriptors);
cout<<"done detecting features"<<endl;
}
return features;
}
// ----------------------------------------------------------------------------
void testVocCreation(const vector<cv::Mat> &features)
{
// branching factor and depth levels
const int k = 9;
const int L = 3;
const WeightingType weight = TF_IDF;
const ScoringType score = L1_NORM;
DBoW3::Vocabulary voc(k, L, weight, score);
cout << "Creating a small " << k << "^" << L << " vocabulary..." << endl;
voc.create(features);
cout << "... done!" << endl;
cout << "Vocabulary information: " << endl
<< voc << endl << endl;
// lets do something with this vocabulary
cout << "Matching images against themselves (0 low, 1 high): " << endl;
BowVector v1, v2;
for(size_t i = 0; i < features.size(); i++)
{
voc.transform(features[i], v1);
for(size_t j = 0; j < features.size(); j++)
{
voc.transform(features[j], v2);
double score = voc.score(v1, v2);
cout << "Image " << i << " vs Image " << j << ": " << score << endl;
}
}
// save the vocabulary to disk
cout << endl << "Saving vocabulary..." << endl;
voc.save("small_voc.yml.gz");
cout << "Done" << endl;
}
////// ----------------------------------------------------------------------------
void testDatabase(const vector<cv::Mat > &features)
{
cout << "Creating a small database..." << endl;
// load the vocabulary from disk
Vocabulary voc("small_voc.yml.gz");
Database db(voc, false, 0); // false = do not use direct index
// (so ignore the last param)
// The direct index is useful if we want to retrieve the features that
// belong to some vocabulary node.
// db creates a copy of the vocabulary, we may get rid of "voc" now
// add images to the database
for(size_t i = 0; i < features.size(); i++)
db.add(features[i]);
cout << "... done!" << endl;
cout << "Database information: " << endl << db << endl;
// and query the database
cout << "Querying the database: " << endl;
QueryResults ret;
for(size_t i = 0; i < features.size(); i++)
{
db.query(features[i], ret, 4);
// ret[0] is always the same image in this case, because we added it to the
// database. ret[1] is the second best match.
cout << "Searching for Image " << i << ". " << ret << endl;
}
cout << endl;
// we can save the database. The created file includes the vocabulary
// and the entries added
cout << "Saving database..." << endl;
db.save("small_db.yml.gz");
cout << "... done!" << endl;
// once saved, we can load it again
cout << "Retrieving database once again..." << endl;
Database db2("small_db.yml.gz");
cout << "... done! This is: " << endl << db2 << endl;
}
// ----------------------------------------------------------------------------
int main(int argc,char **argv)
{
try{
CmdLineParser cml(argc,argv);
if (cml["-h"] || argc<=2){
cerr<<"Usage: descriptor_name image0 image1 ... \n\t descriptors:brisk,surf,orb ,akaze(only if using opencv 3)"<<endl;
return -1;
}
string descriptor=argv[1];
auto images=readImagePaths(argc,argv,2);
vector< cv::Mat > features= loadFeatures(images,descriptor);
testVocCreation(features);
testDatabase(features);
}catch(std::exception &ex){
cerr<<ex.what()<<endl;
}
return 0;
}