include/opencv2/flann/flann.hpp
Go to the documentation of this file.
00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                           License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Third party copyrights are property of their respective owners.
00016 //
00017 // Redistribution and use in source and binary forms, with or without modification,
00018 // are permitted provided that the following conditions are met:
00019 //
00020 //   * Redistribution's of source code must retain the above copyright notice,
00021 //     this list of conditions and the following disclaimer.
00022 //
00023 //   * Redistribution's in binary form must reproduce the above copyright notice,
00024 //     this list of conditions and the following disclaimer in the documentation
00025 //     and/or other materials provided with the distribution.
00026 //
00027 //   * The name of the copyright holders may not be used to endorse or promote products
00028 //     derived from this software without specific prior written permission.
00029 //
00030 // This software is provided by the copyright holders and contributors "as is" and
00031 // any express or implied warranties, including, but not limited to, the implied
00032 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00033 // In no event shall the Intel Corporation or contributors be liable for any direct,
00034 // indirect, incidental, special, exemplary, or consequential damages
00035 // (including, but not limited to, procurement of substitute goods or services;
00036 // loss of use, data, or profits; or business interruption) however caused
00037 // and on any theory of liability, whether in contract, strict liability,
00038 // or tort (including negligence or otherwise) arising in any way out of
00039 // the use of this software, even if advised of the possibility of such damage.
00040 //
00041 //M*/
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 // bring the flann parameters into this namespace
00076 using ::cvflann::get_param;
00077 using ::cvflann::print_params;
00078 
00079 // bring the flann distances into this namespace
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         // providing backwards compatibility for L2 and L1 distances (most common)
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 } } // namespace cv::flann
00424 
00425 #endif // __cplusplus
00426 
00427 #endif