00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef _OPENCV_FLANN_HPP_
00044 #define _OPENCV_FLANN_HPP_
00045
00046 #ifdef __cplusplus
00047
00048 #include "opencv2/core/types_c.h"
00049 #include "opencv2/core/core.hpp"
00050 #include "opencv2/flann/flann_base.hpp"
00051 #include "opencv2/flann/miniflann.hpp"
00052
00053 namespace cvflann
00054 {
00055 CV_EXPORTS flann_distance_t flann_distance_type();
00056 FLANN_DEPRECATED CV_EXPORTS void set_distance_type(flann_distance_t distance_type, int order);
00057 }
00058
00059
00060 namespace cv
00061 {
00062 namespace flann
00063 {
00064
00065 template <typename T> struct CvType {};
00066 template <> struct CvType<unsigned char> { static int type() { return CV_8U; } };
00067 template <> struct CvType<char> { static int type() { return CV_8S; } };
00068 template <> struct CvType<unsigned short> { static int type() { return CV_16U; } };
00069 template <> struct CvType<short> { static int type() { return CV_16S; } };
00070 template <> struct CvType<int> { static int type() { return CV_32S; } };
00071 template <> struct CvType<float> { static int type() { return CV_32F; } };
00072 template <> struct CvType<double> { static int type() { return CV_64F; } };
00073
00074
00075
00076 using ::cvflann::get_param;
00077 using ::cvflann::print_params;
00078
00079
00080 using ::cvflann::L2_Simple;
00081 using ::cvflann::L2;
00082 using ::cvflann::L1;
00083 using ::cvflann::MinkowskiDistance;
00084 using ::cvflann::MaxDistance;
00085 using ::cvflann::HammingLUT;
00086 using ::cvflann::Hamming;
00087 using ::cvflann::Hamming2;
00088 using ::cvflann::HistIntersectionDistance;
00089 using ::cvflann::HellingerDistance;
00090 using ::cvflann::ChiSquareDistance;
00091 using ::cvflann::KL_Divergence;
00092
00093
00094
00095 template <typename Distance>
00096 class GenericIndex
00097 {
00098 public:
00099 typedef typename Distance::ElementType ElementType;
00100 typedef typename Distance::ResultType DistanceType;
00101
00102 GenericIndex(const Mat& features, const ::cvflann::IndexParams& params, Distance distance = Distance());
00103
00104 ~GenericIndex();
00105
00106 void knnSearch(const vector<ElementType>& query, vector<int>& indices,
00107 vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& params);
00108 void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);
00109
00110 int radiusSearch(const vector<ElementType>& query, vector<int>& indices,
00111 vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& params);
00112 int radiusSearch(const Mat& query, Mat& indices, Mat& dists,
00113 DistanceType radius, const ::cvflann::SearchParams& params);
00114
00115 void save(std::string filename) { nnIndex->save(filename); }
00116
00117 int veclen() const { return nnIndex->veclen(); }
00118
00119 int size() const { return nnIndex->size(); }
00120
00121 ::cvflann::IndexParams getParameters() { return nnIndex->getParameters(); }
00122
00123 FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() { return nnIndex->getIndexParameters(); }
00124
00125 private:
00126 ::cvflann::Index<Distance>* nnIndex;
00127 };
00128
00129
00130 #define FLANN_DISTANCE_CHECK \
00131 if ( ::cvflann::flann_distance_type() != cvflann::FLANN_DIST_L2) { \
00132 printf("[WARNING] You are using cv::flann::Index (or cv::flann::GenericIndex) and have also changed "\
00133 "the distance using cvflann::set_distance_type. This is no longer working as expected "\
00134 "(cv::flann::Index always uses L2). You should create the index templated on the distance, "\
00135 "for example for L1 distance use: GenericIndex< L1<float> > \n"); \
00136 }
00137
00138
00139 template <typename Distance>
00140 GenericIndex<Distance>::GenericIndex(const Mat& dataset, const ::cvflann::IndexParams& params, Distance distance)
00141 {
00142 CV_Assert(dataset.type() == CvType<ElementType>::type());
00143 CV_Assert(dataset.isContinuous());
00144 ::cvflann::Matrix<ElementType> m_dataset((ElementType*)dataset.ptr<ElementType>(0), dataset.rows, dataset.cols);
00145
00146 nnIndex = new ::cvflann::Index<Distance>(m_dataset, params, distance);
00147
00148 FLANN_DISTANCE_CHECK
00149
00150 nnIndex->buildIndex();
00151 }
00152
00153 template <typename Distance>
00154 GenericIndex<Distance>::~GenericIndex()
00155 {
00156 delete nnIndex;
00157 }
00158
00159 template <typename Distance>
00160 void GenericIndex<Distance>::knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& searchParams)
00161 {
00162 ::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
00163 ::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
00164 ::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
00165
00166 FLANN_DISTANCE_CHECK
00167
00168 nnIndex->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
00169 }
00170
00171
00172 template <typename Distance>
00173 void GenericIndex<Distance>::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams)
00174 {
00175 CV_Assert(queries.type() == CvType<ElementType>::type());
00176 CV_Assert(queries.isContinuous());
00177 ::cvflann::Matrix<ElementType> m_queries((ElementType*)queries.ptr<ElementType>(0), queries.rows, queries.cols);
00178
00179 CV_Assert(indices.type() == CV_32S);
00180 CV_Assert(indices.isContinuous());
00181 ::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
00182
00183 CV_Assert(dists.type() == CvType<DistanceType>::type());
00184 CV_Assert(dists.isContinuous());
00185 ::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
00186
00187 FLANN_DISTANCE_CHECK
00188
00189 nnIndex->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
00190 }
00191
00192 template <typename Distance>
00193 int GenericIndex<Distance>::radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
00194 {
00195 ::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
00196 ::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
00197 ::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
00198
00199 FLANN_DISTANCE_CHECK
00200
00201 return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
00202 }
00203
00204 template <typename Distance>
00205 int GenericIndex<Distance>::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
00206 {
00207 CV_Assert(query.type() == CvType<ElementType>::type());
00208 CV_Assert(query.isContinuous());
00209 ::cvflann::Matrix<ElementType> m_query((ElementType*)query.ptr<ElementType>(0), query.rows, query.cols);
00210
00211 CV_Assert(indices.type() == CV_32S);
00212 CV_Assert(indices.isContinuous());
00213 ::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
00214
00215 CV_Assert(dists.type() == CvType<DistanceType>::type());
00216 CV_Assert(dists.isContinuous());
00217 ::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
00218
00219 FLANN_DISTANCE_CHECK
00220
00221 return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
00222 }
00223
00227 template <typename T>
00228 class
00229 #ifndef _MSC_VER
00230 FLANN_DEPRECATED
00231 #endif
00232 Index_ {
00233 public:
00234 typedef typename L2<T>::ElementType ElementType;
00235 typedef typename L2<T>::ResultType DistanceType;
00236
00237 Index_(const Mat& features, const ::cvflann::IndexParams& params);
00238
00239 ~Index_();
00240
00241 void knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& params);
00242 void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);
00243
00244 int radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& params);
00245 int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params);
00246
00247 void save(std::string filename)
00248 {
00249 if (nnIndex_L1) nnIndex_L1->save(filename);
00250 if (nnIndex_L2) nnIndex_L2->save(filename);
00251 }
00252
00253 int veclen() const
00254 {
00255 if (nnIndex_L1) return nnIndex_L1->veclen();
00256 if (nnIndex_L2) return nnIndex_L2->veclen();
00257 }
00258
00259 int size() const
00260 {
00261 if (nnIndex_L1) return nnIndex_L1->size();
00262 if (nnIndex_L2) return nnIndex_L2->size();
00263 }
00264
00265 ::cvflann::IndexParams getParameters()
00266 {
00267 if (nnIndex_L1) return nnIndex_L1->getParameters();
00268 if (nnIndex_L2) return nnIndex_L2->getParameters();
00269
00270 }
00271
00272 FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters()
00273 {
00274 if (nnIndex_L1) return nnIndex_L1->getIndexParameters();
00275 if (nnIndex_L2) return nnIndex_L2->getIndexParameters();
00276 }
00277
00278 private:
00279
00280 ::cvflann::Index< L2<ElementType> >* nnIndex_L2;
00281 ::cvflann::Index< L1<ElementType> >* nnIndex_L1;
00282 };
00283
00284 #ifdef _MSC_VER
00285 template <typename T>
00286 class FLANN_DEPRECATED Index_;
00287 #endif
00288
00289 template <typename T>
00290 Index_<T>::Index_(const Mat& dataset, const ::cvflann::IndexParams& params)
00291 {
00292 printf("[WARNING] The cv::flann::Index_<T> class is deperecated, use cv::flann::GenericIndex<Distance> instead\n");
00293
00294 CV_Assert(dataset.type() == CvType<ElementType>::type());
00295 CV_Assert(dataset.isContinuous());
00296 ::cvflann::Matrix<ElementType> m_dataset((ElementType*)dataset.ptr<ElementType>(0), dataset.rows, dataset.cols);
00297
00298 if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) {
00299 nnIndex_L1 = NULL;
00300 nnIndex_L2 = new ::cvflann::Index< L2<ElementType> >(m_dataset, params);
00301 }
00302 else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) {
00303 nnIndex_L1 = new ::cvflann::Index< L1<ElementType> >(m_dataset, params);
00304 nnIndex_L2 = NULL;
00305 }
00306 else {
00307 printf("[ERROR] cv::flann::Index_<T> only provides backwards compatibility for the L1 and L2 distances. "
00308 "For other distance types you must use cv::flann::GenericIndex<Distance>\n");
00309 CV_Assert(0);
00310 }
00311 if (nnIndex_L1) nnIndex_L1->buildIndex();
00312 if (nnIndex_L2) nnIndex_L2->buildIndex();
00313 }
00314
00315 template <typename T>
00316 Index_<T>::~Index_()
00317 {
00318 if (nnIndex_L1) delete nnIndex_L1;
00319 if (nnIndex_L2) delete nnIndex_L2;
00320 }
00321
00322 template <typename T>
00323 void Index_<T>::knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& searchParams)
00324 {
00325 ::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
00326 ::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
00327 ::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
00328
00329 if (nnIndex_L1) nnIndex_L1->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
00330 if (nnIndex_L2) nnIndex_L2->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
00331 }
00332
00333
00334 template <typename T>
00335 void Index_<T>::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams)
00336 {
00337 CV_Assert(queries.type() == CvType<ElementType>::type());
00338 CV_Assert(queries.isContinuous());
00339 ::cvflann::Matrix<ElementType> m_queries((ElementType*)queries.ptr<ElementType>(0), queries.rows, queries.cols);
00340
00341 CV_Assert(indices.type() == CV_32S);
00342 CV_Assert(indices.isContinuous());
00343 ::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
00344
00345 CV_Assert(dists.type() == CvType<DistanceType>::type());
00346 CV_Assert(dists.isContinuous());
00347 ::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
00348
00349 if (nnIndex_L1) nnIndex_L1->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
00350 if (nnIndex_L2) nnIndex_L2->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
00351 }
00352
00353 template <typename T>
00354 int Index_<T>::radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
00355 {
00356 ::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
00357 ::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
00358 ::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
00359
00360 if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
00361 if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
00362 }
00363
00364 template <typename T>
00365 int Index_<T>::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
00366 {
00367 CV_Assert(query.type() == CvType<ElementType>::type());
00368 CV_Assert(query.isContinuous());
00369 ::cvflann::Matrix<ElementType> m_query((ElementType*)query.ptr<ElementType>(0), query.rows, query.cols);
00370
00371 CV_Assert(indices.type() == CV_32S);
00372 CV_Assert(indices.isContinuous());
00373 ::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
00374
00375 CV_Assert(dists.type() == CvType<DistanceType>::type());
00376 CV_Assert(dists.isContinuous());
00377 ::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
00378
00379 if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
00380 if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
00381 }
00382
00383
00384 template <typename Distance>
00385 int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params,
00386 Distance d = Distance())
00387 {
00388 typedef typename Distance::ElementType ElementType;
00389 typedef typename Distance::ResultType DistanceType;
00390
00391 CV_Assert(features.type() == CvType<ElementType>::type());
00392 CV_Assert(features.isContinuous());
00393 ::cvflann::Matrix<ElementType> m_features((ElementType*)features.ptr<ElementType>(0), features.rows, features.cols);
00394
00395 CV_Assert(centers.type() == CvType<DistanceType>::type());
00396 CV_Assert(centers.isContinuous());
00397 ::cvflann::Matrix<DistanceType> m_centers((DistanceType*)centers.ptr<DistanceType>(0), centers.rows, centers.cols);
00398
00399 return ::cvflann::hierarchicalClustering<Distance>(m_features, m_centers, params, d);
00400 }
00401
00402
00403 template <typename ELEM_TYPE, typename DIST_TYPE>
00404 FLANN_DEPRECATED int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params)
00405 {
00406 printf("[WARNING] cv::flann::hierarchicalClustering<ELEM_TYPE,DIST_TYPE> is deprecated, use "
00407 "cv::flann::hierarchicalClustering<Distance> instead\n");
00408
00409 if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) {
00410 return hierarchicalClustering< L2<ELEM_TYPE> >(features, centers, params);
00411 }
00412 else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) {
00413 return hierarchicalClustering< L1<ELEM_TYPE> >(features, centers, params);
00414 }
00415 else {
00416 printf("[ERROR] cv::flann::hierarchicalClustering<ELEM_TYPE,DIST_TYPE> only provides backwards "
00417 "compatibility for the L1 and L2 distances. "
00418 "For other distance types you must use cv::flann::hierarchicalClustering<Distance>\n");
00419 CV_Assert(0);
00420 }
00421 }
00422
00423 } }
00424
00425 #endif // __cplusplus
00426
00427 #endif