/********************************************************************* * Software License Agreement (BSD License) * * Copyright (c) 2009, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions 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. * * Neither the name of the Willow Garage nor the names of its * contributors may 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 * COPYRIGHT OWNER 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. *********************************************************************/ #include "precomp.hpp" #include "flann/flann.hpp" namespace cv { namespace flann { ::cvflann::Index* LinearIndexParams::createIndex(const Mat& dataset) const { CV_Assert(dataset.type() == CV_32F); CV_Assert(dataset.isContinuous()); // TODO: fix ::cvflann::Matrix class so it can be constructed with a const float* ::cvflann::Matrix mat(dataset.rows, dataset.cols, (float*)dataset.ptr(0)); return new ::cvflann::Index(mat, ::cvflann::LinearIndexParams()); } ::cvflann::Index* KDTreeIndexParams::createIndex(const Mat& dataset) const { CV_Assert(dataset.type() == CV_32F); CV_Assert(dataset.isContinuous()); // TODO: fix ::cvflann::Matrix class so it can be constructed with a const float* ::cvflann::Matrix mat(dataset.rows, dataset.cols, (float*)dataset.ptr(0)); return new ::cvflann::Index(mat, ::cvflann::KDTreeIndexParams(trees)); } ::cvflann::Index* KMeansIndexParams::createIndex(const Mat& dataset) const { CV_Assert(dataset.type() == CV_32F); CV_Assert(dataset.isContinuous()); // TODO: fix ::cvflann::Matrix class so it can be constructed with a const float* ::cvflann::Matrix mat(dataset.rows, dataset.cols, (float*)dataset.ptr(0)); return new ::cvflann::Index(mat, ::cvflann::KMeansIndexParams(branching,iterations, (::flann_centers_init_t)centers_init, cb_index)); } ::cvflann::Index* CompositeIndexParams::createIndex(const Mat& dataset) const { CV_Assert(dataset.type() == CV_32F); CV_Assert(dataset.isContinuous()); // TODO: fix ::cvflann::Matrix class so it can be constructed with a const float* ::cvflann::Matrix mat(dataset.rows, dataset.cols, (float*)dataset.ptr(0)); return new ::cvflann::Index(mat, ::cvflann::CompositeIndexParams(trees, branching, iterations, (::flann_centers_init_t)centers_init, cb_index)); } ::cvflann::Index* AutotunedIndexParams::createIndex(const Mat& dataset) const { CV_Assert(dataset.type() == CV_32F); CV_Assert(dataset.isContinuous()); // TODO: fix ::cvflann::Matrix class so it can be constructed with a const float* ::cvflann::Matrix mat(dataset.rows, dataset.cols, (float*)dataset.ptr(0)); return new ::cvflann::Index(mat, ::cvflann::AutotunedIndexParams(target_precision, build_weight, memory_weight, sample_fraction)); } ::cvflann::Index* SavedIndexParams::createIndex(const Mat& dataset) const { CV_Assert(dataset.type() == CV_32F); CV_Assert(dataset.isContinuous()); // TODO: fix ::cvflann::Matrix class so it can be constructed with a const float* ::cvflann::Matrix mat(dataset.rows, dataset.cols, (float*)dataset.ptr(0)); return new ::cvflann::Index(mat, ::cvflann::SavedIndexParams(filename)); } Index::Index(const Mat& dataset, const IndexParams& params) { nnIndex = params.createIndex(dataset); } Index::~Index() { delete nnIndex; } void Index::knnSearch(const vector& query, vector& indices, vector& dists, int knn, const SearchParams& searchParams) { ::cvflann::Matrix m_query(1, query.size(), (float*)&query[0]); ::cvflann::Matrix m_indices(1, indices.size(), &indices[0]); ::cvflann::Matrix m_dists(1, dists.size(), &dists[0]); nnIndex->knnSearch(m_query,m_indices,m_dists,knn,::cvflann::SearchParams(searchParams.checks)); } void Index::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const SearchParams& searchParams) { CV_Assert(queries.type() == CV_32F); CV_Assert(queries.isContinuous()); ::cvflann::Matrix m_queries(queries.rows, queries.cols, (float*)queries.ptr(0)); CV_Assert(indices.type() == CV_32S); CV_Assert(indices.isContinuous()); ::cvflann::Matrix m_indices(indices.rows, indices.cols, (int*)indices.ptr(0)); CV_Assert(dists.type() == CV_32F); CV_Assert(dists.isContinuous()); ::cvflann::Matrix m_dists(dists.rows, dists.cols, (float*)dists.ptr(0)); nnIndex->knnSearch(m_queries,m_indices,m_dists,knn,::cvflann::SearchParams(searchParams.checks)); } int Index::radiusSearch(const vector& query, vector& indices, vector& dists, float radius, const SearchParams& searchParams) { ::cvflann::Matrix m_query(1, query.size(), (float*)&query[0]); ::cvflann::Matrix m_indices(1, indices.size(), &indices[0]); ::cvflann::Matrix m_dists(1, dists.size(), &dists[0]); return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,::cvflann::SearchParams(searchParams.checks)); } int Index::radiusSearch(const Mat& query, Mat& indices, Mat& dists, float radius, const SearchParams& searchParams) { CV_Assert(query.type() == CV_32F); CV_Assert(query.isContinuous()); ::cvflann::Matrix m_query(query.rows, query.cols, (float*)query.ptr(0)); CV_Assert(indices.type() == CV_32S); CV_Assert(indices.isContinuous()); ::cvflann::Matrix m_indices(indices.rows, indices.cols, (int*)indices.ptr(0)); CV_Assert(dists.type() == CV_32F); CV_Assert(dists.isContinuous()); ::cvflann::Matrix m_dists(dists.rows, dists.cols, (float*)dists.ptr(0)); return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,::cvflann::SearchParams(searchParams.checks)); } void Index::save(string filename) { nnIndex->save(filename); } int Index::size() const { return nnIndex->size(); } int Index::veclen() const { return nnIndex->veclen(); } int hierarchicalClustering(const Mat& features, Mat& centers, const KMeansIndexParams& params) { CV_Assert(features.type() == CV_32F); CV_Assert(features.isContinuous()); ::cvflann::Matrix m_features(features.rows, features.cols, (float*)features.ptr(0)); CV_Assert(features.type() == CV_32F); CV_Assert(features.isContinuous()); ::cvflann::Matrix m_centers(centers.rows, centers.cols, (float*)centers.ptr(0)); return ::cvflann::hierarchicalClustering(m_features, m_centers, ::cvflann::KMeansIndexParams(params.branching, params.iterations, (::flann_centers_init_t)params.centers_init, params.cb_index)); } } }