Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/flann/src/miniflann.cpp
16344 views
1
#include "precomp.hpp"
2
3
#define MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES 0
4
5
static cvflann::IndexParams& get_params(const cv::flann::IndexParams& p)
6
{
7
return *(cvflann::IndexParams*)(p.params);
8
}
9
10
cv::flann::IndexParams::~IndexParams()
11
{
12
delete &get_params(*this);
13
}
14
15
namespace cv
16
{
17
18
namespace flann
19
{
20
21
using namespace cvflann;
22
23
IndexParams::IndexParams()
24
{
25
params = new ::cvflann::IndexParams();
26
}
27
28
template<typename T>
29
T getParam(const IndexParams& _p, const String& key, const T& defaultVal=T())
30
{
31
::cvflann::IndexParams& p = get_params(_p);
32
::cvflann::IndexParams::const_iterator it = p.find(key);
33
if( it == p.end() )
34
return defaultVal;
35
return it->second.cast<T>();
36
}
37
38
template<typename T>
39
void setParam(IndexParams& _p, const String& key, const T& value)
40
{
41
::cvflann::IndexParams& p = get_params(_p);
42
p[key] = value;
43
}
44
45
String IndexParams::getString(const String& key, const String& defaultVal) const
46
{
47
return getParam(*this, key, defaultVal);
48
}
49
50
int IndexParams::getInt(const String& key, int defaultVal) const
51
{
52
return getParam(*this, key, defaultVal);
53
}
54
55
double IndexParams::getDouble(const String& key, double defaultVal) const
56
{
57
return getParam(*this, key, defaultVal);
58
}
59
60
61
void IndexParams::setString(const String& key, const String& value)
62
{
63
setParam(*this, key, value);
64
}
65
66
void IndexParams::setInt(const String& key, int value)
67
{
68
setParam(*this, key, value);
69
}
70
71
void IndexParams::setDouble(const String& key, double value)
72
{
73
setParam(*this, key, value);
74
}
75
76
void IndexParams::setFloat(const String& key, float value)
77
{
78
setParam(*this, key, value);
79
}
80
81
void IndexParams::setBool(const String& key, bool value)
82
{
83
setParam(*this, key, value);
84
}
85
86
void IndexParams::setAlgorithm(int value)
87
{
88
setParam(*this, "algorithm", (cvflann::flann_algorithm_t)value);
89
}
90
91
void IndexParams::getAll(std::vector<String>& names,
92
std::vector<FlannIndexType>& types,
93
std::vector<String>& strValues,
94
std::vector<double>& numValues) const
95
{
96
names.clear();
97
types.clear();
98
strValues.clear();
99
numValues.clear();
100
101
::cvflann::IndexParams& p = get_params(*this);
102
::cvflann::IndexParams::const_iterator it = p.begin(), it_end = p.end();
103
104
for( ; it != it_end; ++it )
105
{
106
names.push_back(it->first);
107
try
108
{
109
String val = it->second.cast<String>();
110
types.push_back(FLANN_INDEX_TYPE_STRING);
111
strValues.push_back(val);
112
numValues.push_back(-1);
113
continue;
114
}
115
catch (...) {}
116
117
strValues.push_back(it->second.type().name());
118
119
try
120
{
121
double val = it->second.cast<double>();
122
types.push_back(FLANN_INDEX_TYPE_64F);
123
numValues.push_back(val);
124
continue;
125
}
126
catch (...) {}
127
try
128
{
129
float val = it->second.cast<float>();
130
types.push_back(FLANN_INDEX_TYPE_32F);
131
numValues.push_back(val);
132
continue;
133
}
134
catch (...) {}
135
try
136
{
137
int val = it->second.cast<int>();
138
types.push_back(FLANN_INDEX_TYPE_32S);
139
numValues.push_back(val);
140
continue;
141
}
142
catch (...) {}
143
try
144
{
145
short val = it->second.cast<short>();
146
types.push_back(FLANN_INDEX_TYPE_16S);
147
numValues.push_back(val);
148
continue;
149
}
150
catch (...) {}
151
try
152
{
153
ushort val = it->second.cast<ushort>();
154
types.push_back(FLANN_INDEX_TYPE_16U);
155
numValues.push_back(val);
156
continue;
157
}
158
catch (...) {}
159
try
160
{
161
char val = it->second.cast<char>();
162
types.push_back(FLANN_INDEX_TYPE_8S);
163
numValues.push_back(val);
164
continue;
165
}
166
catch (...) {}
167
try
168
{
169
uchar val = it->second.cast<uchar>();
170
types.push_back(FLANN_INDEX_TYPE_8U);
171
numValues.push_back(val);
172
continue;
173
}
174
catch (...) {}
175
try
176
{
177
bool val = it->second.cast<bool>();
178
types.push_back(FLANN_INDEX_TYPE_BOOL);
179
numValues.push_back(val);
180
continue;
181
}
182
catch (...) {}
183
try
184
{
185
cvflann::flann_algorithm_t val = it->second.cast<cvflann::flann_algorithm_t>();
186
types.push_back(FLANN_INDEX_TYPE_ALGORITHM);
187
numValues.push_back(val);
188
continue;
189
}
190
catch (...) {}
191
192
193
types.push_back((FlannIndexType)-1); // unknown type
194
numValues.push_back(-1);
195
}
196
}
197
198
199
KDTreeIndexParams::KDTreeIndexParams(int trees)
200
{
201
::cvflann::IndexParams& p = get_params(*this);
202
p["algorithm"] = FLANN_INDEX_KDTREE;
203
p["trees"] = trees;
204
}
205
206
LinearIndexParams::LinearIndexParams()
207
{
208
::cvflann::IndexParams& p = get_params(*this);
209
p["algorithm"] = FLANN_INDEX_LINEAR;
210
}
211
212
CompositeIndexParams::CompositeIndexParams(int trees, int branching, int iterations,
213
flann_centers_init_t centers_init, float cb_index )
214
{
215
::cvflann::IndexParams& p = get_params(*this);
216
p["algorithm"] = FLANN_INDEX_KMEANS;
217
// number of randomized trees to use (for kdtree)
218
p["trees"] = trees;
219
// branching factor
220
p["branching"] = branching;
221
// max iterations to perform in one kmeans clustering (kmeans tree)
222
p["iterations"] = iterations;
223
// algorithm used for picking the initial cluster centers for kmeans tree
224
p["centers_init"] = centers_init;
225
// cluster boundary index. Used when searching the kmeans tree
226
p["cb_index"] = cb_index;
227
}
228
229
AutotunedIndexParams::AutotunedIndexParams(float target_precision, float build_weight,
230
float memory_weight, float sample_fraction)
231
{
232
::cvflann::IndexParams& p = get_params(*this);
233
p["algorithm"] = FLANN_INDEX_AUTOTUNED;
234
// precision desired (used for autotuning, -1 otherwise)
235
p["target_precision"] = target_precision;
236
// build tree time weighting factor
237
p["build_weight"] = build_weight;
238
// index memory weighting factor
239
p["memory_weight"] = memory_weight;
240
// what fraction of the dataset to use for autotuning
241
p["sample_fraction"] = sample_fraction;
242
}
243
244
245
KMeansIndexParams::KMeansIndexParams(int branching, int iterations,
246
flann_centers_init_t centers_init, float cb_index )
247
{
248
::cvflann::IndexParams& p = get_params(*this);
249
p["algorithm"] = FLANN_INDEX_KMEANS;
250
// branching factor
251
p["branching"] = branching;
252
// max iterations to perform in one kmeans clustering (kmeans tree)
253
p["iterations"] = iterations;
254
// algorithm used for picking the initial cluster centers for kmeans tree
255
p["centers_init"] = centers_init;
256
// cluster boundary index. Used when searching the kmeans tree
257
p["cb_index"] = cb_index;
258
}
259
260
HierarchicalClusteringIndexParams::HierarchicalClusteringIndexParams(int branching ,
261
flann_centers_init_t centers_init,
262
int trees, int leaf_size)
263
{
264
::cvflann::IndexParams& p = get_params(*this);
265
p["algorithm"] = FLANN_INDEX_HIERARCHICAL;
266
// The branching factor used in the hierarchical clustering
267
p["branching"] = branching;
268
// Algorithm used for picking the initial cluster centers
269
p["centers_init"] = centers_init;
270
// number of parallel trees to build
271
p["trees"] = trees;
272
// maximum leaf size
273
p["leaf_size"] = leaf_size;
274
}
275
276
LshIndexParams::LshIndexParams(int table_number, int key_size, int multi_probe_level)
277
{
278
::cvflann::IndexParams& p = get_params(*this);
279
p["algorithm"] = FLANN_INDEX_LSH;
280
// The number of hash tables to use
281
p["table_number"] = table_number;
282
// The length of the key in the hash tables
283
p["key_size"] = key_size;
284
// Number of levels to use in multi-probe (0 for standard LSH)
285
p["multi_probe_level"] = multi_probe_level;
286
}
287
288
SavedIndexParams::SavedIndexParams(const String& _filename)
289
{
290
String filename = _filename;
291
::cvflann::IndexParams& p = get_params(*this);
292
293
p["algorithm"] = FLANN_INDEX_SAVED;
294
p["filename"] = filename;
295
}
296
297
SearchParams::SearchParams( int checks, float eps, bool sorted )
298
{
299
::cvflann::IndexParams& p = get_params(*this);
300
301
// how many leafs to visit when searching for neighbours (-1 for unlimited)
302
p["checks"] = checks;
303
// search for eps-approximate neighbours (default: 0)
304
p["eps"] = eps;
305
// only for radius search, require neighbours sorted by distance (default: true)
306
p["sorted"] = sorted;
307
}
308
309
310
template<typename Distance, typename IndexType> void
311
buildIndex_(void*& index, const Mat& data, const IndexParams& params, const Distance& dist = Distance())
312
{
313
typedef typename Distance::ElementType ElementType;
314
if(DataType<ElementType>::type != data.type())
315
CV_Error_(Error::StsUnsupportedFormat, ("type=%d\n", data.type()));
316
if(!data.isContinuous())
317
CV_Error(Error::StsBadArg, "Only continuous arrays are supported");
318
319
::cvflann::Matrix<ElementType> dataset((ElementType*)data.data, data.rows, data.cols);
320
IndexType* _index = new IndexType(dataset, get_params(params), dist);
321
322
try
323
{
324
_index->buildIndex();
325
}
326
catch (...)
327
{
328
delete _index;
329
_index = NULL;
330
331
throw;
332
}
333
334
index = _index;
335
}
336
337
template<typename Distance> void
338
buildIndex(void*& index, const Mat& data, const IndexParams& params, const Distance& dist = Distance())
339
{
340
buildIndex_<Distance, ::cvflann::Index<Distance> >(index, data, params, dist);
341
}
342
343
#if CV_NEON
344
typedef ::cvflann::Hamming<uchar> HammingDistance;
345
#else
346
typedef ::cvflann::HammingLUT HammingDistance;
347
#endif
348
349
Index::Index()
350
{
351
index = 0;
352
featureType = CV_32F;
353
algo = FLANN_INDEX_LINEAR;
354
distType = FLANN_DIST_L2;
355
}
356
357
Index::Index(InputArray _data, const IndexParams& params, flann_distance_t _distType)
358
{
359
index = 0;
360
featureType = CV_32F;
361
algo = FLANN_INDEX_LINEAR;
362
distType = FLANN_DIST_L2;
363
build(_data, params, _distType);
364
}
365
366
void Index::build(InputArray _data, const IndexParams& params, flann_distance_t _distType)
367
{
368
CV_INSTRUMENT_REGION();
369
370
release();
371
algo = getParam<flann_algorithm_t>(params, "algorithm", FLANN_INDEX_LINEAR);
372
if( algo == FLANN_INDEX_SAVED )
373
{
374
load(_data, getParam<String>(params, "filename", String()));
375
return;
376
}
377
378
Mat data = _data.getMat();
379
index = 0;
380
featureType = data.type();
381
distType = _distType;
382
383
if ( algo == FLANN_INDEX_LSH)
384
{
385
distType = FLANN_DIST_HAMMING;
386
}
387
388
switch( distType )
389
{
390
case FLANN_DIST_HAMMING:
391
buildIndex< HammingDistance >(index, data, params);
392
break;
393
case FLANN_DIST_L2:
394
buildIndex< ::cvflann::L2<float> >(index, data, params);
395
break;
396
case FLANN_DIST_L1:
397
buildIndex< ::cvflann::L1<float> >(index, data, params);
398
break;
399
#if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
400
case FLANN_DIST_MAX:
401
buildIndex< ::cvflann::MaxDistance<float> >(index, data, params);
402
break;
403
case FLANN_DIST_HIST_INTERSECT:
404
buildIndex< ::cvflann::HistIntersectionDistance<float> >(index, data, params);
405
break;
406
case FLANN_DIST_HELLINGER:
407
buildIndex< ::cvflann::HellingerDistance<float> >(index, data, params);
408
break;
409
case FLANN_DIST_CHI_SQUARE:
410
buildIndex< ::cvflann::ChiSquareDistance<float> >(index, data, params);
411
break;
412
case FLANN_DIST_KL:
413
buildIndex< ::cvflann::KL_Divergence<float> >(index, data, params);
414
break;
415
#endif
416
default:
417
CV_Error(Error::StsBadArg, "Unknown/unsupported distance type");
418
}
419
}
420
421
template<typename IndexType> void deleteIndex_(void* index)
422
{
423
delete (IndexType*)index;
424
}
425
426
template<typename Distance> void deleteIndex(void* index)
427
{
428
deleteIndex_< ::cvflann::Index<Distance> >(index);
429
}
430
431
Index::~Index()
432
{
433
release();
434
}
435
436
void Index::release()
437
{
438
CV_INSTRUMENT_REGION();
439
440
if( !index )
441
return;
442
443
switch( distType )
444
{
445
case FLANN_DIST_HAMMING:
446
deleteIndex< HammingDistance >(index);
447
break;
448
case FLANN_DIST_L2:
449
deleteIndex< ::cvflann::L2<float> >(index);
450
break;
451
case FLANN_DIST_L1:
452
deleteIndex< ::cvflann::L1<float> >(index);
453
break;
454
#if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
455
case FLANN_DIST_MAX:
456
deleteIndex< ::cvflann::MaxDistance<float> >(index);
457
break;
458
case FLANN_DIST_HIST_INTERSECT:
459
deleteIndex< ::cvflann::HistIntersectionDistance<float> >(index);
460
break;
461
case FLANN_DIST_HELLINGER:
462
deleteIndex< ::cvflann::HellingerDistance<float> >(index);
463
break;
464
case FLANN_DIST_CHI_SQUARE:
465
deleteIndex< ::cvflann::ChiSquareDistance<float> >(index);
466
break;
467
case FLANN_DIST_KL:
468
deleteIndex< ::cvflann::KL_Divergence<float> >(index);
469
break;
470
#endif
471
default:
472
CV_Error(Error::StsBadArg, "Unknown/unsupported distance type");
473
}
474
index = 0;
475
}
476
477
template<typename Distance, typename IndexType>
478
void runKnnSearch_(void* index, const Mat& query, Mat& indices, Mat& dists,
479
int knn, const SearchParams& params)
480
{
481
typedef typename Distance::ElementType ElementType;
482
typedef typename Distance::ResultType DistanceType;
483
int type = DataType<ElementType>::type;
484
int dtype = DataType<DistanceType>::type;
485
IndexType* index_ = (IndexType*)index;
486
487
CV_Assert((size_t)knn <= index_->size());
488
CV_Assert(query.type() == type && indices.type() == CV_32S && dists.type() == dtype);
489
CV_Assert(query.isContinuous() && indices.isContinuous() && dists.isContinuous());
490
491
::cvflann::Matrix<ElementType> _query((ElementType*)query.data, query.rows, query.cols);
492
::cvflann::Matrix<int> _indices(indices.ptr<int>(), indices.rows, indices.cols);
493
::cvflann::Matrix<DistanceType> _dists(dists.ptr<DistanceType>(), dists.rows, dists.cols);
494
495
index_->knnSearch(_query, _indices, _dists, knn,
496
(const ::cvflann::SearchParams&)get_params(params));
497
}
498
499
template<typename Distance>
500
void runKnnSearch(void* index, const Mat& query, Mat& indices, Mat& dists,
501
int knn, const SearchParams& params)
502
{
503
runKnnSearch_<Distance, ::cvflann::Index<Distance> >(index, query, indices, dists, knn, params);
504
}
505
506
template<typename Distance, typename IndexType>
507
int runRadiusSearch_(void* index, const Mat& query, Mat& indices, Mat& dists,
508
double radius, const SearchParams& params)
509
{
510
typedef typename Distance::ElementType ElementType;
511
typedef typename Distance::ResultType DistanceType;
512
int type = DataType<ElementType>::type;
513
int dtype = DataType<DistanceType>::type;
514
CV_Assert(query.type() == type && indices.type() == CV_32S && dists.type() == dtype);
515
CV_Assert(query.isContinuous() && indices.isContinuous() && dists.isContinuous());
516
517
::cvflann::Matrix<ElementType> _query((ElementType*)query.data, query.rows, query.cols);
518
::cvflann::Matrix<int> _indices(indices.ptr<int>(), indices.rows, indices.cols);
519
::cvflann::Matrix<DistanceType> _dists(dists.ptr<DistanceType>(), dists.rows, dists.cols);
520
521
return ((IndexType*)index)->radiusSearch(_query, _indices, _dists,
522
saturate_cast<float>(radius),
523
(const ::cvflann::SearchParams&)get_params(params));
524
}
525
526
template<typename Distance>
527
int runRadiusSearch(void* index, const Mat& query, Mat& indices, Mat& dists,
528
double radius, const SearchParams& params)
529
{
530
return runRadiusSearch_<Distance, ::cvflann::Index<Distance> >(index, query, indices, dists, radius, params);
531
}
532
533
534
static void createIndicesDists(OutputArray _indices, OutputArray _dists,
535
Mat& indices, Mat& dists, int rows,
536
int minCols, int maxCols, int dtype)
537
{
538
if( _indices.needed() )
539
{
540
indices = _indices.getMat();
541
if( !indices.isContinuous() || indices.type() != CV_32S ||
542
indices.rows != rows || indices.cols < minCols || indices.cols > maxCols )
543
{
544
if( !indices.isContinuous() )
545
_indices.release();
546
_indices.create( rows, minCols, CV_32S );
547
indices = _indices.getMat();
548
}
549
}
550
else
551
indices.create( rows, minCols, CV_32S );
552
553
if( _dists.needed() )
554
{
555
dists = _dists.getMat();
556
if( !dists.isContinuous() || dists.type() != dtype ||
557
dists.rows != rows || dists.cols < minCols || dists.cols > maxCols )
558
{
559
if( !_dists.isContinuous() )
560
_dists.release();
561
_dists.create( rows, minCols, dtype );
562
dists = _dists.getMat();
563
}
564
}
565
else
566
dists.create( rows, minCols, dtype );
567
}
568
569
570
void Index::knnSearch(InputArray _query, OutputArray _indices,
571
OutputArray _dists, int knn, const SearchParams& params)
572
{
573
CV_INSTRUMENT_REGION();
574
575
Mat query = _query.getMat(), indices, dists;
576
int dtype = distType == FLANN_DIST_HAMMING ? CV_32S : CV_32F;
577
578
createIndicesDists( _indices, _dists, indices, dists, query.rows, knn, knn, dtype );
579
580
switch( distType )
581
{
582
case FLANN_DIST_HAMMING:
583
runKnnSearch<HammingDistance>(index, query, indices, dists, knn, params);
584
break;
585
case FLANN_DIST_L2:
586
runKnnSearch< ::cvflann::L2<float> >(index, query, indices, dists, knn, params);
587
break;
588
case FLANN_DIST_L1:
589
runKnnSearch< ::cvflann::L1<float> >(index, query, indices, dists, knn, params);
590
break;
591
#if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
592
case FLANN_DIST_MAX:
593
runKnnSearch< ::cvflann::MaxDistance<float> >(index, query, indices, dists, knn, params);
594
break;
595
case FLANN_DIST_HIST_INTERSECT:
596
runKnnSearch< ::cvflann::HistIntersectionDistance<float> >(index, query, indices, dists, knn, params);
597
break;
598
case FLANN_DIST_HELLINGER:
599
runKnnSearch< ::cvflann::HellingerDistance<float> >(index, query, indices, dists, knn, params);
600
break;
601
case FLANN_DIST_CHI_SQUARE:
602
runKnnSearch< ::cvflann::ChiSquareDistance<float> >(index, query, indices, dists, knn, params);
603
break;
604
case FLANN_DIST_KL:
605
runKnnSearch< ::cvflann::KL_Divergence<float> >(index, query, indices, dists, knn, params);
606
break;
607
#endif
608
default:
609
CV_Error(Error::StsBadArg, "Unknown/unsupported distance type");
610
}
611
}
612
613
int Index::radiusSearch(InputArray _query, OutputArray _indices,
614
OutputArray _dists, double radius, int maxResults,
615
const SearchParams& params)
616
{
617
CV_INSTRUMENT_REGION();
618
619
Mat query = _query.getMat(), indices, dists;
620
int dtype = distType == FLANN_DIST_HAMMING ? CV_32S : CV_32F;
621
CV_Assert( maxResults > 0 );
622
createIndicesDists( _indices, _dists, indices, dists, query.rows, maxResults, INT_MAX, dtype );
623
624
if( algo == FLANN_INDEX_LSH )
625
CV_Error( Error::StsNotImplemented, "LSH index does not support radiusSearch operation" );
626
627
switch( distType )
628
{
629
case FLANN_DIST_HAMMING:
630
return runRadiusSearch< HammingDistance >(index, query, indices, dists, radius, params);
631
632
case FLANN_DIST_L2:
633
return runRadiusSearch< ::cvflann::L2<float> >(index, query, indices, dists, radius, params);
634
case FLANN_DIST_L1:
635
return runRadiusSearch< ::cvflann::L1<float> >(index, query, indices, dists, radius, params);
636
#if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
637
case FLANN_DIST_MAX:
638
return runRadiusSearch< ::cvflann::MaxDistance<float> >(index, query, indices, dists, radius, params);
639
case FLANN_DIST_HIST_INTERSECT:
640
return runRadiusSearch< ::cvflann::HistIntersectionDistance<float> >(index, query, indices, dists, radius, params);
641
case FLANN_DIST_HELLINGER:
642
return runRadiusSearch< ::cvflann::HellingerDistance<float> >(index, query, indices, dists, radius, params);
643
case FLANN_DIST_CHI_SQUARE:
644
return runRadiusSearch< ::cvflann::ChiSquareDistance<float> >(index, query, indices, dists, radius, params);
645
case FLANN_DIST_KL:
646
return runRadiusSearch< ::cvflann::KL_Divergence<float> >(index, query, indices, dists, radius, params);
647
#endif
648
default:
649
CV_Error(Error::StsBadArg, "Unknown/unsupported distance type");
650
}
651
return -1;
652
}
653
654
flann_distance_t Index::getDistance() const
655
{
656
return distType;
657
}
658
659
flann_algorithm_t Index::getAlgorithm() const
660
{
661
return algo;
662
}
663
664
template<typename IndexType> void saveIndex_(const Index* index0, const void* index, FILE* fout)
665
{
666
IndexType* _index = (IndexType*)index;
667
::cvflann::save_header(fout, *_index);
668
// some compilers may store short enumerations as bytes,
669
// so make sure we always write integers (which are 4-byte values in any modern C compiler)
670
int idistType = (int)index0->getDistance();
671
::cvflann::save_value<int>(fout, idistType);
672
_index->saveIndex(fout);
673
}
674
675
template<typename Distance> void saveIndex(const Index* index0, const void* index, FILE* fout)
676
{
677
saveIndex_< ::cvflann::Index<Distance> >(index0, index, fout);
678
}
679
680
void Index::save(const String& filename) const
681
{
682
CV_INSTRUMENT_REGION();
683
684
FILE* fout = fopen(filename.c_str(), "wb");
685
if (fout == NULL)
686
CV_Error_( Error::StsError, ("Can not open file %s for writing FLANN index\n", filename.c_str()) );
687
688
switch( distType )
689
{
690
case FLANN_DIST_HAMMING:
691
saveIndex< HammingDistance >(this, index, fout);
692
break;
693
case FLANN_DIST_L2:
694
saveIndex< ::cvflann::L2<float> >(this, index, fout);
695
break;
696
case FLANN_DIST_L1:
697
saveIndex< ::cvflann::L1<float> >(this, index, fout);
698
break;
699
#if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
700
case FLANN_DIST_MAX:
701
saveIndex< ::cvflann::MaxDistance<float> >(this, index, fout);
702
break;
703
case FLANN_DIST_HIST_INTERSECT:
704
saveIndex< ::cvflann::HistIntersectionDistance<float> >(this, index, fout);
705
break;
706
case FLANN_DIST_HELLINGER:
707
saveIndex< ::cvflann::HellingerDistance<float> >(this, index, fout);
708
break;
709
case FLANN_DIST_CHI_SQUARE:
710
saveIndex< ::cvflann::ChiSquareDistance<float> >(this, index, fout);
711
break;
712
case FLANN_DIST_KL:
713
saveIndex< ::cvflann::KL_Divergence<float> >(this, index, fout);
714
break;
715
#endif
716
default:
717
fclose(fout);
718
fout = 0;
719
CV_Error(Error::StsBadArg, "Unknown/unsupported distance type");
720
}
721
if( fout )
722
fclose(fout);
723
}
724
725
726
template<typename Distance, typename IndexType>
727
bool loadIndex_(Index* index0, void*& index, const Mat& data, FILE* fin, const Distance& dist=Distance())
728
{
729
typedef typename Distance::ElementType ElementType;
730
CV_Assert(DataType<ElementType>::type == data.type() && data.isContinuous());
731
732
::cvflann::Matrix<ElementType> dataset((ElementType*)data.data, data.rows, data.cols);
733
734
::cvflann::IndexParams params;
735
params["algorithm"] = index0->getAlgorithm();
736
IndexType* _index = new IndexType(dataset, params, dist);
737
_index->loadIndex(fin);
738
index = _index;
739
return true;
740
}
741
742
template<typename Distance>
743
bool loadIndex(Index* index0, void*& index, const Mat& data, FILE* fin, const Distance& dist=Distance())
744
{
745
return loadIndex_<Distance, ::cvflann::Index<Distance> >(index0, index, data, fin, dist);
746
}
747
748
bool Index::load(InputArray _data, const String& filename)
749
{
750
Mat data = _data.getMat();
751
bool ok = true;
752
release();
753
FILE* fin = fopen(filename.c_str(), "rb");
754
if (fin == NULL)
755
return false;
756
757
::cvflann::IndexHeader header = ::cvflann::load_header(fin);
758
algo = header.index_type;
759
featureType = header.data_type == FLANN_UINT8 ? CV_8U :
760
header.data_type == FLANN_INT8 ? CV_8S :
761
header.data_type == FLANN_UINT16 ? CV_16U :
762
header.data_type == FLANN_INT16 ? CV_16S :
763
header.data_type == FLANN_INT32 ? CV_32S :
764
header.data_type == FLANN_FLOAT32 ? CV_32F :
765
header.data_type == FLANN_FLOAT64 ? CV_64F : -1;
766
767
if( (int)header.rows != data.rows || (int)header.cols != data.cols ||
768
featureType != data.type() )
769
{
770
fprintf(stderr, "Reading FLANN index error: the saved data size (%d, %d) or type (%d) is different from the passed one (%d, %d), %d\n",
771
(int)header.rows, (int)header.cols, featureType, data.rows, data.cols, data.type());
772
fclose(fin);
773
return false;
774
}
775
776
int idistType = 0;
777
::cvflann::load_value(fin, idistType);
778
distType = (flann_distance_t)idistType;
779
780
if( !((distType == FLANN_DIST_HAMMING && featureType == CV_8U) ||
781
(distType != FLANN_DIST_HAMMING && featureType == CV_32F)) )
782
{
783
fprintf(stderr, "Reading FLANN index error: unsupported feature type %d for the index type %d\n", featureType, algo);
784
fclose(fin);
785
return false;
786
}
787
788
switch( distType )
789
{
790
case FLANN_DIST_HAMMING:
791
loadIndex< HammingDistance >(this, index, data, fin);
792
break;
793
case FLANN_DIST_L2:
794
loadIndex< ::cvflann::L2<float> >(this, index, data, fin);
795
break;
796
case FLANN_DIST_L1:
797
loadIndex< ::cvflann::L1<float> >(this, index, data, fin);
798
break;
799
#if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
800
case FLANN_DIST_MAX:
801
loadIndex< ::cvflann::MaxDistance<float> >(this, index, data, fin);
802
break;
803
case FLANN_DIST_HIST_INTERSECT:
804
loadIndex< ::cvflann::HistIntersectionDistance<float> >(index, data, fin);
805
break;
806
case FLANN_DIST_HELLINGER:
807
loadIndex< ::cvflann::HellingerDistance<float> >(this, index, data, fin);
808
break;
809
case FLANN_DIST_CHI_SQUARE:
810
loadIndex< ::cvflann::ChiSquareDistance<float> >(this, index, data, fin);
811
break;
812
case FLANN_DIST_KL:
813
loadIndex< ::cvflann::KL_Divergence<float> >(this, index, data, fin);
814
break;
815
#endif
816
default:
817
fprintf(stderr, "Reading FLANN index error: unsupported distance type %d\n", distType);
818
ok = false;
819
}
820
821
if( fin )
822
fclose(fin);
823
return ok;
824
}
825
826
}
827
828
}
829
830