Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2008, Xavier Delacour, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 // 2008-05-13, Xavier Delacour <xavier.delacour (at) gmail.com>
     43 
     44 #include "_cv.h"
     45 
     46 #if !defined _MSC_VER || defined __ICL || _MSC_VER >= 1400
     47 #include "_cvkdtree.hpp"
     48 
     49 // * write up some docs
     50 
     51 // * removing __valuetype parameter from CvKDTree and using virtuals instead
     52 // * of void* data here could simplify things.
     53 
     54 struct CvFeatureTree {
     55 
     56   template <class __scalartype, int __cvtype>
     57   struct deref {
     58     typedef __scalartype scalar_type;
     59     typedef double accum_type;
     60 
     61     CvMat* mat;
     62     deref(CvMat* _mat) : mat(_mat) {
     63       assert(CV_ELEM_SIZE1(__cvtype) == sizeof(__scalartype));
     64     }
     65     scalar_type operator() (int i, int j) const {
     66       return *((scalar_type*)(mat->data.ptr + i * mat->step) + j);
     67     }
     68   };
     69 
     70 #define dispatch_cvtype(mat, c) \
     71     switch (CV_MAT_DEPTH((mat)->type)) { \
     72     case CV_32F: \
     73       { typedef CvKDTree<int, deref<float, CV_32F> > tree_type; c; break; } \
     74     case CV_64F: \
     75       { typedef CvKDTree<int, deref<double, CV_64F> > tree_type; c; break; } \
     76     default: assert(0); \
     77     }
     78 
     79   CvMat* mat;
     80   void* data;
     81 
     82   template <class __treetype>
     83   void find_nn(CvMat* d, int k, int emax, CvMat* results, CvMat* dist) {
     84     __treetype* tr = (__treetype*) data;
     85     uchar* dptr = d->data.ptr;
     86     uchar* resultsptr = results->data.ptr;
     87     uchar* distptr = dist->data.ptr;
     88     typename __treetype::bbf_nn_pqueue nn;
     89 
     90     assert(d->cols == tr->dims());
     91     assert(results->rows == d->rows);
     92     assert(results->rows == dist->rows);
     93     assert(results->cols == k);
     94     assert(dist->cols == k);
     95 
     96     for (int j = 0; j < d->rows; ++j) {
     97       typename __treetype::scalar_type* dj = (typename __treetype::scalar_type*) dptr;
     98 
     99       int* resultsj = (int*) resultsptr;
    100       double* distj = (double*) distptr;
    101       tr->find_nn_bbf(dj, k, emax, nn);
    102 
    103       assert((int)nn.size() <= k);
    104       for (unsigned int j = 0; j < nn.size(); ++j) {
    105 	*resultsj++ = *nn[j].p;
    106 	*distj++ = nn[j].dist;
    107       }
    108       std::fill(resultsj, resultsj + k - nn.size(), -1);
    109       std::fill(distj, distj + k - nn.size(), 0);
    110 
    111       dptr += d->step;
    112       resultsptr += results->step;
    113       distptr += dist->step;
    114     }
    115   }
    116 
    117   template <class __treetype>
    118   int find_ortho_range(CvMat* bounds_min, CvMat* bounds_max,
    119 		       CvMat* results) {
    120     int rn = results->rows * results->cols;
    121     std::vector<int> inbounds;
    122     dispatch_cvtype(mat, ((__treetype*)data)->
    123 		    find_ortho_range((typename __treetype::scalar_type*)bounds_min->data.ptr,
    124 				     (typename __treetype::scalar_type*)bounds_max->data.ptr,
    125 				     inbounds));
    126     std::copy(inbounds.begin(),
    127 	      inbounds.begin() + std::min((int)inbounds.size(), rn),
    128 	      (int*) results->data.ptr);
    129     return inbounds.size();
    130   }
    131 
    132   CvFeatureTree(const CvFeatureTree& x);
    133   CvFeatureTree& operator= (const CvFeatureTree& rhs);
    134 public:
    135   CvFeatureTree(CvMat* _mat) : mat(_mat) {
    136     // * a flag parameter should tell us whether
    137     // * (a) user ensures *mat outlives *this and is unchanged,
    138     // * (b) we take reference and user ensures mat is unchanged,
    139     // * (c) we copy data, (d) we own and release data.
    140 
    141     std::vector<int> tmp(mat->rows);
    142     for (unsigned int j = 0; j < tmp.size(); ++j)
    143       tmp[j] = j;
    144 
    145     dispatch_cvtype(mat, data = new tree_type
    146 		    (&tmp[0], &tmp[0] + tmp.size(), mat->cols,
    147 		     tree_type::deref_type(mat)));
    148   }
    149   ~CvFeatureTree() {
    150     dispatch_cvtype(mat, delete (tree_type*) data);
    151   }
    152 
    153   int dims() {
    154     int d = 0;
    155     dispatch_cvtype(mat, d = ((tree_type*) data)->dims());
    156     return d;
    157   }
    158   int type() {
    159     return mat->type;
    160   }
    161 
    162   void find_nn(CvMat* d, int k, int emax, CvMat* results, CvMat* dist) {
    163     assert(CV_MAT_TYPE(d->type) == CV_MAT_TYPE(mat->type));
    164     assert(CV_MAT_TYPE(dist->type) == CV_64FC1);
    165     assert(CV_MAT_TYPE(results->type) == CV_32SC1);
    166 
    167     dispatch_cvtype(mat, find_nn<tree_type>
    168 		    (d, k, emax, results, dist));
    169   }
    170   int find_ortho_range(CvMat* bounds_min, CvMat* bounds_max,
    171 			CvMat* results) {
    172     assert(CV_MAT_TYPE(bounds_min->type) == CV_MAT_TYPE(mat->type));
    173     assert(CV_MAT_TYPE(bounds_min->type) == CV_MAT_TYPE(bounds_max->type));
    174     assert(bounds_min->rows * bounds_min->cols == dims());
    175     assert(bounds_max->rows * bounds_max->cols == dims());
    176 
    177     int count = 0;
    178     dispatch_cvtype(mat, count = find_ortho_range<tree_type>
    179 		    (bounds_min, bounds_max,results));
    180     return count;
    181   }
    182 };
    183 
    184 
    185 
    186 CvFeatureTree* cvCreateFeatureTree(CvMat* desc) {
    187   __BEGIN__;
    188   CV_FUNCNAME("cvCreateFeatureTree");
    189 
    190   if (CV_MAT_TYPE(desc->type) != CV_32FC1 &&
    191       CV_MAT_TYPE(desc->type) != CV_64FC1)
    192     CV_ERROR(CV_StsUnsupportedFormat, "descriptors must be either CV_32FC1 or CV_64FC1");
    193 
    194   return new CvFeatureTree(desc);
    195   __END__;
    196 
    197   return 0;
    198 }
    199 
    200 void cvReleaseFeatureTree(CvFeatureTree* tr) {
    201   delete tr;
    202 }
    203 
    204 // desc is m x d set of candidate points.
    205 // results is m x k set of row indices of matching points.
    206 // dist is m x k distance to matching points.
    207 void cvFindFeatures(CvFeatureTree* tr, CvMat* desc,
    208 		    CvMat* results, CvMat* dist, int k, int emax) {
    209   bool free_desc = false;
    210   int dims = tr->dims();
    211   int type = tr->type();
    212 
    213   __BEGIN__;
    214   CV_FUNCNAME("cvFindFeatures");
    215 
    216   if (desc->cols != dims)
    217     CV_ERROR(CV_StsUnmatchedSizes, "desc columns be equal feature dimensions");
    218   if (results->rows != desc->rows && results->cols != k)
    219     CV_ERROR(CV_StsUnmatchedSizes, "results and desc must be same height");
    220   if (dist->rows != desc->rows && dist->cols != k)
    221     CV_ERROR(CV_StsUnmatchedSizes, "dist and desc must be same height");
    222   if (CV_MAT_TYPE(results->type) != CV_32SC1)
    223     CV_ERROR(CV_StsUnsupportedFormat, "results must be CV_32SC1");
    224   if (CV_MAT_TYPE(dist->type) != CV_64FC1)
    225     CV_ERROR(CV_StsUnsupportedFormat, "dist must be CV_64FC1");
    226 
    227   if (CV_MAT_TYPE(type) != CV_MAT_TYPE(desc->type)) {
    228     CvMat* old_desc = desc;
    229     desc = cvCreateMat(desc->rows, desc->cols, type);
    230     cvConvert(old_desc, desc);
    231     free_desc = true;
    232   }
    233 
    234   tr->find_nn(desc, k, emax, results, dist);
    235 
    236   __END__;
    237 
    238   if (free_desc)
    239     cvReleaseMat(&desc);
    240 }
    241 
    242 int cvFindFeaturesBoxed(CvFeatureTree* tr,
    243 			CvMat* bounds_min, CvMat* bounds_max,
    244 			CvMat* results) {
    245   int nr = -1;
    246   bool free_bounds = false;
    247   int dims = tr->dims();
    248   int type = tr->type();
    249 
    250   __BEGIN__;
    251   CV_FUNCNAME("cvFindFeaturesBoxed");
    252 
    253   if (bounds_min->cols * bounds_min->rows != dims ||
    254       bounds_max->cols * bounds_max->rows != dims)
    255     CV_ERROR(CV_StsUnmatchedSizes, "bounds_{min,max} must 1 x dims or dims x 1");
    256   if (CV_MAT_TYPE(bounds_min->type) != CV_MAT_TYPE(bounds_max->type))
    257     CV_ERROR(CV_StsUnmatchedFormats, "bounds_{min,max} must have same type");
    258   if (CV_MAT_TYPE(results->type) != CV_32SC1)
    259     CV_ERROR(CV_StsUnsupportedFormat, "results must be CV_32SC1");
    260 
    261   if (CV_MAT_TYPE(bounds_min->type) != CV_MAT_TYPE(type)) {
    262     free_bounds = true;
    263 
    264     CvMat* old_bounds_min = bounds_min;
    265     bounds_min = cvCreateMat(bounds_min->rows, bounds_min->cols, type);
    266     cvConvert(old_bounds_min, bounds_min);
    267 
    268     CvMat* old_bounds_max = bounds_max;
    269     bounds_max = cvCreateMat(bounds_max->rows, bounds_max->cols, type);
    270     cvConvert(old_bounds_max, bounds_max);
    271   }
    272 
    273   nr = tr->find_ortho_range(bounds_min, bounds_max, results);
    274 
    275   __END__;
    276   if (free_bounds) {
    277     cvReleaseMat(&bounds_min);
    278     cvReleaseMat(&bounds_max);
    279   }
    280 
    281   return nr;
    282 }
    283 #endif
    284