All Downloads are FREE. Search and download functionalities are using the official Maven repository.

srcnativelibs.Include.OpenCV.opencv2.flann.flann.hpp Maven / Gradle / Ivy

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef _OPENCV_FLANN_HPP_
#define _OPENCV_FLANN_HPP_

#ifdef __cplusplus

#include "opencv2/core/types_c.h"
#include "opencv2/core/core.hpp"
#include "opencv2/flann/flann_base.hpp"
#include "opencv2/flann/miniflann.hpp"

namespace cvflann
{
    CV_EXPORTS flann_distance_t flann_distance_type();
    FLANN_DEPRECATED CV_EXPORTS void set_distance_type(flann_distance_t distance_type, int order);
}


namespace cv
{
namespace flann
{

template  struct CvType {};
template <> struct CvType { static int type() { return CV_8U; } };
template <> struct CvType { static int type() { return CV_8S; } };
template <> struct CvType { static int type() { return CV_16U; } };
template <> struct CvType { static int type() { return CV_16S; } };
template <> struct CvType { static int type() { return CV_32S; } };
template <> struct CvType { static int type() { return CV_32F; } };
template <> struct CvType { static int type() { return CV_64F; } };


// bring the flann parameters into this namespace
using ::cvflann::get_param;
using ::cvflann::print_params;

// bring the flann distances into this namespace
using ::cvflann::L2_Simple;
using ::cvflann::L2;
using ::cvflann::L1;
using ::cvflann::MinkowskiDistance;
using ::cvflann::MaxDistance;
using ::cvflann::HammingLUT;
using ::cvflann::Hamming;
using ::cvflann::Hamming2;
using ::cvflann::HistIntersectionDistance;
using ::cvflann::HellingerDistance;
using ::cvflann::ChiSquareDistance;
using ::cvflann::KL_Divergence;



template 
class GenericIndex
{
public:
        typedef typename Distance::ElementType ElementType;
        typedef typename Distance::ResultType DistanceType;

        GenericIndex(const Mat& features, const ::cvflann::IndexParams& params, Distance distance = Distance());

        ~GenericIndex();

        void knnSearch(const vector& query, vector& indices,
                       vector& dists, int knn, const ::cvflann::SearchParams& params);
        void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);

        int radiusSearch(const vector& query, vector& indices,
                         vector& dists, DistanceType radius, const ::cvflann::SearchParams& params);
        int radiusSearch(const Mat& query, Mat& indices, Mat& dists,
                         DistanceType radius, const ::cvflann::SearchParams& params);

        void save(std::string filename) { nnIndex->save(filename); }

        int veclen() const { return nnIndex->veclen(); }

        int size() const { return nnIndex->size(); }

        ::cvflann::IndexParams getParameters() { return nnIndex->getParameters(); }

        FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() { return nnIndex->getIndexParameters(); }

private:
        ::cvflann::Index* nnIndex;
};


#define FLANN_DISTANCE_CHECK \
    if ( ::cvflann::flann_distance_type() != cvflann::FLANN_DIST_L2) { \
        printf("[WARNING] You are using cv::flann::Index (or cv::flann::GenericIndex) and have also changed "\
        "the distance using cvflann::set_distance_type. This is no longer working as expected "\
        "(cv::flann::Index always uses L2). You should create the index templated on the distance, "\
        "for example for L1 distance use: GenericIndex< L1 > \n"); \
    }


template 
GenericIndex::GenericIndex(const Mat& dataset, const ::cvflann::IndexParams& params, Distance distance)
{
    CV_Assert(dataset.type() == CvType::type());
    CV_Assert(dataset.isContinuous());
    ::cvflann::Matrix m_dataset((ElementType*)dataset.ptr(0), dataset.rows, dataset.cols);

    nnIndex = new ::cvflann::Index(m_dataset, params, distance);

    FLANN_DISTANCE_CHECK

    nnIndex->buildIndex();
}

template 
GenericIndex::~GenericIndex()
{
    delete nnIndex;
}

template 
void GenericIndex::knnSearch(const vector& query, vector& indices, vector& dists, int knn, const ::cvflann::SearchParams& searchParams)
{
    ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size());
    ::cvflann::Matrix m_indices(&indices[0], 1, indices.size());
    ::cvflann::Matrix m_dists(&dists[0], 1, dists.size());

    FLANN_DISTANCE_CHECK

    nnIndex->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
}


template 
void GenericIndex::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams)
{
    CV_Assert(queries.type() == CvType::type());
    CV_Assert(queries.isContinuous());
    ::cvflann::Matrix m_queries((ElementType*)queries.ptr(0), queries.rows, queries.cols);

    CV_Assert(indices.type() == CV_32S);
    CV_Assert(indices.isContinuous());
    ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols);

    CV_Assert(dists.type() == CvType::type());
    CV_Assert(dists.isContinuous());
    ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols);

    FLANN_DISTANCE_CHECK

    nnIndex->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
}

template 
int GenericIndex::radiusSearch(const vector& query, vector& indices, vector& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
{
    ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size());
    ::cvflann::Matrix m_indices(&indices[0], 1, indices.size());
    ::cvflann::Matrix m_dists(&dists[0], 1, dists.size());

    FLANN_DISTANCE_CHECK

    return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
}

template 
int GenericIndex::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
{
    CV_Assert(query.type() == CvType::type());
    CV_Assert(query.isContinuous());
    ::cvflann::Matrix m_query((ElementType*)query.ptr(0), query.rows, query.cols);

    CV_Assert(indices.type() == CV_32S);
    CV_Assert(indices.isContinuous());
    ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols);

    CV_Assert(dists.type() == CvType::type());
    CV_Assert(dists.isContinuous());
    ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols);

    FLANN_DISTANCE_CHECK

    return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
}

/**
 * @deprecated Use GenericIndex class instead
 */
template 
class
#ifndef _MSC_VER
 FLANN_DEPRECATED
#endif
 Index_ {
public:
        typedef typename L2::ElementType ElementType;
        typedef typename L2::ResultType DistanceType;

    Index_(const Mat& features, const ::cvflann::IndexParams& params);

    ~Index_();

    void knnSearch(const vector& query, vector& indices, vector& dists, int knn, const ::cvflann::SearchParams& params);
    void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);

    int radiusSearch(const vector& query, vector& indices, vector& dists, DistanceType radius, const ::cvflann::SearchParams& params);
    int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params);

    void save(std::string filename)
        {
            if (nnIndex_L1) nnIndex_L1->save(filename);
            if (nnIndex_L2) nnIndex_L2->save(filename);
        }

    int veclen() const
    {
            if (nnIndex_L1) return nnIndex_L1->veclen();
            if (nnIndex_L2) return nnIndex_L2->veclen();
        }

    int size() const
    {
            if (nnIndex_L1) return nnIndex_L1->size();
            if (nnIndex_L2) return nnIndex_L2->size();
        }

        ::cvflann::IndexParams getParameters()
        {
            if (nnIndex_L1) return nnIndex_L1->getParameters();
            if (nnIndex_L2) return nnIndex_L2->getParameters();

        }

        FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters()
        {
            if (nnIndex_L1) return nnIndex_L1->getIndexParameters();
            if (nnIndex_L2) return nnIndex_L2->getIndexParameters();
        }

private:
        // providing backwards compatibility for L2 and L1 distances (most common)
        ::cvflann::Index< L2 >* nnIndex_L2;
        ::cvflann::Index< L1 >* nnIndex_L1;
};

#ifdef _MSC_VER
template 
class FLANN_DEPRECATED Index_;
#endif

template 
Index_::Index_(const Mat& dataset, const ::cvflann::IndexParams& params)
{
    printf("[WARNING] The cv::flann::Index_ class is deperecated, use cv::flann::GenericIndex instead\n");

    CV_Assert(dataset.type() == CvType::type());
    CV_Assert(dataset.isContinuous());
    ::cvflann::Matrix m_dataset((ElementType*)dataset.ptr(0), dataset.rows, dataset.cols);

    if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) {
        nnIndex_L1 = NULL;
        nnIndex_L2 = new ::cvflann::Index< L2 >(m_dataset, params);
    }
    else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) {
        nnIndex_L1 = new ::cvflann::Index< L1 >(m_dataset, params);
        nnIndex_L2 = NULL;
    }
    else {
        printf("[ERROR] cv::flann::Index_ only provides backwards compatibility for the L1 and L2 distances. "
        "For other distance types you must use cv::flann::GenericIndex\n");
        CV_Assert(0);
    }
    if (nnIndex_L1) nnIndex_L1->buildIndex();
    if (nnIndex_L2) nnIndex_L2->buildIndex();
}

template 
Index_::~Index_()
{
    if (nnIndex_L1) delete nnIndex_L1;
    if (nnIndex_L2) delete nnIndex_L2;
}

template 
void Index_::knnSearch(const vector& query, vector& indices, vector& dists, int knn, const ::cvflann::SearchParams& searchParams)
{
    ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size());
    ::cvflann::Matrix m_indices(&indices[0], 1, indices.size());
    ::cvflann::Matrix m_dists(&dists[0], 1, dists.size());

    if (nnIndex_L1) nnIndex_L1->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
    if (nnIndex_L2) nnIndex_L2->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
}


template 
void Index_::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams)
{
    CV_Assert(queries.type() == CvType::type());
    CV_Assert(queries.isContinuous());
    ::cvflann::Matrix m_queries((ElementType*)queries.ptr(0), queries.rows, queries.cols);

    CV_Assert(indices.type() == CV_32S);
    CV_Assert(indices.isContinuous());
    ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols);

    CV_Assert(dists.type() == CvType::type());
    CV_Assert(dists.isContinuous());
    ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols);

    if (nnIndex_L1) nnIndex_L1->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
    if (nnIndex_L2) nnIndex_L2->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
}

template 
int Index_::radiusSearch(const vector& query, vector& indices, vector& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
{
    ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size());
    ::cvflann::Matrix m_indices(&indices[0], 1, indices.size());
    ::cvflann::Matrix m_dists(&dists[0], 1, dists.size());

    if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
    if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
}

template 
int Index_::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
{
    CV_Assert(query.type() == CvType::type());
    CV_Assert(query.isContinuous());
    ::cvflann::Matrix m_query((ElementType*)query.ptr(0), query.rows, query.cols);

    CV_Assert(indices.type() == CV_32S);
    CV_Assert(indices.isContinuous());
    ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols);

    CV_Assert(dists.type() == CvType::type());
    CV_Assert(dists.isContinuous());
    ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols);

    if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
    if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
}


template 
int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params,
                           Distance d = Distance())
{
    typedef typename Distance::ElementType ElementType;
    typedef typename Distance::ResultType DistanceType;

    CV_Assert(features.type() == CvType::type());
    CV_Assert(features.isContinuous());
    ::cvflann::Matrix m_features((ElementType*)features.ptr(0), features.rows, features.cols);

    CV_Assert(centers.type() == CvType::type());
    CV_Assert(centers.isContinuous());
    ::cvflann::Matrix m_centers((DistanceType*)centers.ptr(0), centers.rows, centers.cols);

    return ::cvflann::hierarchicalClustering(m_features, m_centers, params, d);
}


template 
FLANN_DEPRECATED int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params)
{
    printf("[WARNING] cv::flann::hierarchicalClustering is deprecated, use "
        "cv::flann::hierarchicalClustering instead\n");

    if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) {
        return hierarchicalClustering< L2 >(features, centers, params);
    }
    else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) {
        return hierarchicalClustering< L1 >(features, centers, params);
    }
    else {
        printf("[ERROR] cv::flann::hierarchicalClustering only provides backwards "
        "compatibility for the L1 and L2 distances. "
        "For other distance types you must use cv::flann::hierarchicalClustering\n");
        CV_Assert(0);
    }
}

} } // namespace cv::flann

#endif // __cplusplus

#endif




© 2015 - 2025 Weber Informatics LLC | Privacy Policy