16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2008, Xavier Delacour, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 2008-05-13, Xavier Delacour <xavier.delacour@gmail.com>
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h"
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if !defined _MSC_VER || defined __ICL || _MSC_VER >= 1400
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cvkdtree.hpp"
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * write up some docs
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * removing __valuetype parameter from CvKDTree and using virtuals instead
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * of void* data here could simplify things.
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct CvFeatureTree {
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  template <class __scalartype, int __cvtype>
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  struct deref {
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    typedef __scalartype scalar_type;
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    typedef double accum_type;
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* mat;
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    deref(CvMat* _mat) : mat(_mat) {
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      assert(CV_ELEM_SIZE1(__cvtype) == sizeof(__scalartype));
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scalar_type operator() (int i, int j) const {
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      return *((scalar_type*)(mat->data.ptr + i * mat->step) + j);
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  };
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define dispatch_cvtype(mat, c) \
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    switch (CV_MAT_DEPTH((mat)->type)) { \
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_32F: \
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      { typedef CvKDTree<int, deref<float, CV_32F> > tree_type; c; break; } \
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_64F: \
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      { typedef CvKDTree<int, deref<double, CV_64F> > tree_type; c; break; } \
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    default: assert(0); \
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CvMat* mat;
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  void* data;
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  template <class __treetype>
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  void find_nn(CvMat* d, int k, int emax, CvMat* results, CvMat* dist) {
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __treetype* tr = (__treetype*) data;
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* dptr = d->data.ptr;
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* resultsptr = results->data.ptr;
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* distptr = dist->data.ptr;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    typename __treetype::bbf_nn_pqueue nn;
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(d->cols == tr->dims());
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(results->rows == d->rows);
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(results->rows == dist->rows);
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(results->cols == k);
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(dist->cols == k);
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for (int j = 0; j < d->rows; ++j) {
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      typename __treetype::scalar_type* dj = (typename __treetype::scalar_type*) dptr;
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      int* resultsj = (int*) resultsptr;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      double* distj = (double*) distptr;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      tr->find_nn_bbf(dj, k, emax, nn);
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      assert((int)nn.size() <= k);
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for (unsigned int j = 0; j < nn.size(); ++j) {
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	*resultsj++ = *nn[j].p;
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	*distj++ = nn[j].dist;
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      std::fill(resultsj, resultsj + k - nn.size(), -1);
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      std::fill(distj, distj + k - nn.size(), 0);
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      dptr += d->step;
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      resultsptr += results->step;
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      distptr += dist->step;
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  template <class __treetype>
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int find_ortho_range(CvMat* bounds_min, CvMat* bounds_max,
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		       CvMat* results) {
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int rn = results->rows * results->cols;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    std::vector<int> inbounds;
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dispatch_cvtype(mat, ((__treetype*)data)->
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    find_ortho_range((typename __treetype::scalar_type*)bounds_min->data.ptr,
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				     (typename __treetype::scalar_type*)bounds_max->data.ptr,
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				     inbounds));
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    std::copy(inbounds.begin(),
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	      inbounds.begin() + std::min((int)inbounds.size(), rn),
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	      (int*) results->data.ptr);
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return inbounds.size();
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CvFeatureTree(const CvFeatureTree& x);
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CvFeatureTree& operator= (const CvFeatureTree& rhs);
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennpublic:
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CvFeatureTree(CvMat* _mat) : mat(_mat) {
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // * a flag parameter should tell us whether
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // * (a) user ensures *mat outlives *this and is unchanged,
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // * (b) we take reference and user ensures mat is unchanged,
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // * (c) we copy data, (d) we own and release data.
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    std::vector<int> tmp(mat->rows);
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for (unsigned int j = 0; j < tmp.size(); ++j)
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      tmp[j] = j;
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dispatch_cvtype(mat, data = new tree_type
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    (&tmp[0], &tmp[0] + tmp.size(), mat->cols,
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		     tree_type::deref_type(mat)));
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  ~CvFeatureTree() {
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dispatch_cvtype(mat, delete (tree_type*) data);
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int dims() {
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int d = 0;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dispatch_cvtype(mat, d = ((tree_type*) data)->dims());
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return d;
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int type() {
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return mat->type;
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  void find_nn(CvMat* d, int k, int emax, CvMat* results, CvMat* dist) {
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(CV_MAT_TYPE(d->type) == CV_MAT_TYPE(mat->type));
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(CV_MAT_TYPE(dist->type) == CV_64FC1);
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(CV_MAT_TYPE(results->type) == CV_32SC1);
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dispatch_cvtype(mat, find_nn<tree_type>
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    (d, k, emax, results, dist));
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int find_ortho_range(CvMat* bounds_min, CvMat* bounds_max,
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			CvMat* results) {
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(CV_MAT_TYPE(bounds_min->type) == CV_MAT_TYPE(mat->type));
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(CV_MAT_TYPE(bounds_min->type) == CV_MAT_TYPE(bounds_max->type));
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(bounds_min->rows * bounds_min->cols == dims());
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(bounds_max->rows * bounds_max->cols == dims());
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = 0;
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dispatch_cvtype(mat, count = find_ortho_range<tree_type>
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    (bounds_min, bounds_max,results));
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvFeatureTree* cvCreateFeatureTree(CvMat* desc) {
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  __BEGIN__;
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CV_FUNCNAME("cvCreateFeatureTree");
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(desc->type) != CV_32FC1 &&
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CV_MAT_TYPE(desc->type) != CV_64FC1)
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnsupportedFormat, "descriptors must be either CV_32FC1 or CV_64FC1");
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  return new CvFeatureTree(desc);
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  __END__;
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  return 0;
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid cvReleaseFeatureTree(CvFeatureTree* tr) {
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  delete tr;
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// desc is m x d set of candidate points.
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// results is m x k set of row indices of matching points.
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// dist is m x k distance to matching points.
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid cvFindFeatures(CvFeatureTree* tr, CvMat* desc,
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    CvMat* results, CvMat* dist, int k, int emax) {
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  bool free_desc = false;
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int dims = tr->dims();
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int type = tr->type();
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  __BEGIN__;
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CV_FUNCNAME("cvFindFeatures");
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (desc->cols != dims)
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnmatchedSizes, "desc columns be equal feature dimensions");
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (results->rows != desc->rows && results->cols != k)
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnmatchedSizes, "results and desc must be same height");
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (dist->rows != desc->rows && dist->cols != k)
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnmatchedSizes, "dist and desc must be same height");
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(results->type) != CV_32SC1)
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnsupportedFormat, "results must be CV_32SC1");
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(dist->type) != CV_64FC1)
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnsupportedFormat, "dist must be CV_64FC1");
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(type) != CV_MAT_TYPE(desc->type)) {
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* old_desc = desc;
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    desc = cvCreateMat(desc->rows, desc->cols, type);
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvConvert(old_desc, desc);
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    free_desc = true;
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  tr->find_nn(desc, k, emax, results, dist);
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  __END__;
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (free_desc)
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&desc);
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint cvFindFeaturesBoxed(CvFeatureTree* tr,
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			CvMat* bounds_min, CvMat* bounds_max,
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			CvMat* results) {
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int nr = -1;
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  bool free_bounds = false;
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int dims = tr->dims();
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  int type = tr->type();
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  __BEGIN__;
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CV_FUNCNAME("cvFindFeaturesBoxed");
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (bounds_min->cols * bounds_min->rows != dims ||
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      bounds_max->cols * bounds_max->rows != dims)
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnmatchedSizes, "bounds_{min,max} must 1 x dims or dims x 1");
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(bounds_min->type) != CV_MAT_TYPE(bounds_max->type))
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnmatchedFormats, "bounds_{min,max} must have same type");
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(results->type) != CV_32SC1)
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ERROR(CV_StsUnsupportedFormat, "results must be CV_32SC1");
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (CV_MAT_TYPE(bounds_min->type) != CV_MAT_TYPE(type)) {
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    free_bounds = true;
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* old_bounds_min = bounds_min;
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bounds_min = cvCreateMat(bounds_min->rows, bounds_min->cols, type);
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvConvert(old_bounds_min, bounds_min);
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* old_bounds_max = bounds_max;
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bounds_max = cvCreateMat(bounds_max->rows, bounds_max->cols, type);
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvConvert(old_bounds_max, bounds_max);
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  nr = tr->find_ortho_range(bounds_min, bounds_max, results);
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  __END__;
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  if (free_bounds) {
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&bounds_min);
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&bounds_max);
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  }
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  return nr;
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
284