PageRenderTime 37ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/fawkes-0.4.2/src/firevision/classifiers/sift.cpp

#
C++ | 258 lines | 137 code | 34 blank | 87 comment | 14 complexity | 4a7db1d489cbc4b0425cd00390a80c01 MD5 | raw file
Possible License(s): GPL-2.0
  1. /***************************************************************************
  2. * sift.cpp - Feature-based classifier using OpenCV structures
  3. *
  4. * Created: Mon Mar 15 15:47:11 2008
  5. * Copyright 2008 Stefan Schiffer [stefanschiffer.de]
  6. *
  7. ****************************************************************************/
  8. /* This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version. A runtime exception applies to
  12. * this software (see LICENSE.GPL_WRE file mentioned below for details).
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Library General Public License for more details.
  18. *
  19. * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
  20. */
  21. #include <iostream>
  22. #include <vector>
  23. #include <classifiers/sift.h>
  24. //#ifdef SIFT_TIMETRACKER
  25. #include <utils/time/clock.h>
  26. #include <utils/time/tracker.h>
  27. //#endif
  28. extern "C" {
  29. #include <sift/sift.h>
  30. #include <sift/imgfeatures.h>
  31. #include <sift/kdtree.h>
  32. #include <sift/utils.h>
  33. #include <sift/xform.h>
  34. }
  35. #include <core/exception.h>
  36. #include <core/exceptions/software.h>
  37. #include <fvutils/color/colorspaces.h>
  38. #include <fvutils/color/conversions.h>
  39. #include <opencv/cv.h>
  40. #include <opencv/cxcore.h>
  41. #include <opencv/highgui.h>
  42. using namespace fawkes;
  43. namespace firevision {
  44. #if 0 /* just to make Emacs auto-indent happy */
  45. }
  46. #endif
  47. /** @class SiftClassifier <classifiers/sift.h>
  48. * SIFT classifier.
  49. *
  50. * This class provides a classifier that uses OpenCV to detect objects in a given
  51. * image by matching features using SIFT. The objects are reported back as regions
  52. * of interest. Each ROI contains an object.
  53. *
  54. * This code is based on the sift package provided by Rob Hess.
  55. * at http://web.engr.oregonstate.edu/~hess/
  56. *
  57. * @author Stefan Schiffer
  58. */
  59. /** Constructor.
  60. * @param object_file file that contains the object to detect
  61. * @param pixel_width width of images that will be processed
  62. * @param pixel_height height of images that will be processed
  63. * @param kdtree_bbf_max_nn_chks maximum number of keypoint NN candidates to check during BBF search
  64. * @param nn_sq_dist_ratio_thr threshold on squared ratio of distances between NN and 2nd NN
  65. * @param flags flags, not used yet.
  66. */
  67. SiftClassifier::SiftClassifier( const char * object_file,
  68. unsigned int pixel_width, unsigned int pixel_height,
  69. int kdtree_bbf_max_nn_chks, float nn_sq_dist_ratio_thr, int flags)
  70. : Classifier("SiftClassifier")
  71. {
  72. __kdtree_bbf_max_nn_chks = kdtree_bbf_max_nn_chks;
  73. __nn_sq_dist_ratio_thr = nn_sq_dist_ratio_thr;
  74. __flags = flags;
  75. //#ifdef SIFT_TIMETRACKER
  76. __tt = new TimeTracker();
  77. __loop_count = 0;
  78. __ttc_objconv = __tt->add_class("ObjectConvert");
  79. __ttc_objfeat = __tt->add_class("ObjectFeatures");
  80. __ttc_imgconv = __tt->add_class("ImageConvert");
  81. __ttc_imgfeat = __tt->add_class("ImageFeatures");
  82. __ttc_matchin = __tt->add_class("Matching");
  83. __ttc_roimerg = __tt->add_class("MergeROIs");
  84. //#endif
  85. //#ifdef SIFT_TIMETRACKER
  86. __tt->ping_start(__ttc_objconv);
  87. //#endif
  88. __obj_img = cvLoadImage( object_file, 1 );
  89. if ( ! __obj_img ) {
  90. throw Exception("Could not load object file");
  91. }
  92. //#ifdef SIFT_TIMETRACKER
  93. __tt->ping_end(__ttc_objconv);
  94. //#endif
  95. //#ifdef SIFT_TIMETRACKER
  96. __tt->ping_start(__ttc_objfeat);
  97. //#endif
  98. __obj_num_features = 0;
  99. __obj_num_features = sift_features( __obj_img, &__obj_features );
  100. if ( ! __obj_num_features > 0 ) {
  101. throw Exception("Could not compute object features");
  102. }
  103. std::cout << "SiftClassifier(classify): computed '" << __obj_num_features << "' features from object" << std::endl;
  104. //cvReleaseImage(&__obj_img);
  105. //#ifdef SIFT_TIMETRACKER
  106. __tt->ping_end(__ttc_objfeat);
  107. //#endif
  108. // create space for OpenCV image
  109. __image = cvCreateImage(cvSize(pixel_width, pixel_height), IPL_DEPTH_8U, 3);
  110. }
  111. /** Destructor. */
  112. SiftClassifier::~SiftClassifier()
  113. {
  114. //
  115. cvReleaseImage(&__obj_img);
  116. cvReleaseImage(&__image);
  117. }
  118. std::list< ROI > *
  119. SiftClassifier::classify()
  120. {
  121. //#ifdef SIFT_TIMETRACKER
  122. __tt->ping_start(0);
  123. //#endif
  124. // list of ROIs to return
  125. std::list< ROI > *rv = new std::list< ROI >();
  126. struct feature * feat;
  127. struct feature** nbrs;
  128. struct kd_node* kd_root;
  129. CvPoint pt1, pt2;
  130. // for ROI calculation
  131. CvPoint ftpt;
  132. std::vector< CvPoint > ftlist;
  133. //= new std::vector< CvPoint >();
  134. int x_min = _width;
  135. int y_min = _height;
  136. int x_max = 0;
  137. int y_max = 0;
  138. double d0, d1;// = 0.0;
  139. int k, m = 0;
  140. //#ifdef SIFT_TIMETRACKER
  141. __tt->ping_start(__ttc_imgconv);
  142. //#endif
  143. //std::cout << "SiftClassifier(classify): convert frame to IplImage" << std::endl;
  144. convert(YUV422_PLANAR, BGR, _src, (unsigned char *)__image->imageData, _width, _height);
  145. //#ifdef SIFT_TIMETRACKER
  146. __tt->ping_end(__ttc_imgconv);
  147. //#endif
  148. //#ifdef SIFT_TIMETRACKER
  149. __tt->ping_start(__ttc_imgfeat);
  150. //#endif
  151. //std::cout << "SiftClassifier(classify): compute features on current frame " << std::endl;
  152. int num_img_ft = sift_features( __image, &__img_features );
  153. kd_root = kdtree_build( __img_features, num_img_ft );
  154. //#ifdef SIFT_TIMETRACKER
  155. __tt->ping_end(__ttc_imgfeat);
  156. //#endif
  157. if( ! kd_root ) {
  158. std::cerr << "SiftClassifier(classify): KD-Root NULL!" << std::endl;
  159. }
  160. //#ifdef SIFT_TIMETRACKER
  161. __tt->ping_start(__ttc_matchin);
  162. //#endif
  163. std::cout << "SiftClassifier(classify): matching ..." << std::endl;
  164. for( int i = 0; i < __obj_num_features; ++i ) {
  165. //std::cout << "SiftClassifier(classify): ... feature '" << i << "'" << std::endl;
  166. feat = __obj_features + i;
  167. k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, __kdtree_bbf_max_nn_chks );
  168. if( k == 2 )
  169. {
  170. d0 = descr_dist_sq( feat, nbrs[0] );
  171. d1 = descr_dist_sq( feat, nbrs[1] );
  172. if( d0 < d1 * __nn_sq_dist_ratio_thr )
  173. {
  174. pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );
  175. pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );
  176. m++;
  177. __obj_features[i].fwd_match = nbrs[0];
  178. // save matched feature points
  179. ftpt = cvPoint( cvRound( nbrs[0]->x), cvRound( nbrs[0]->y ) );
  180. ftlist.push_back(ftpt);
  181. // save matched features as ROIs
  182. ROI r( pt2.x-5, pt2.y-5, 11, 11, _width, _height);
  183. rv->push_back(r);
  184. }
  185. }
  186. free( nbrs );
  187. }
  188. std::cout << "SiftClassifier(classify): found '" << m << "' matches" << std::endl;
  189. kdtree_release( kd_root );
  190. //#ifdef SIFT_TIMETRACKER
  191. __tt->ping_end(__ttc_matchin);
  192. //#endif
  193. //#ifdef SIFT_TIMETRACKER
  194. __tt->ping_start(__ttc_roimerg);
  195. //#endif
  196. std::cout << "SiftClassifier(classify): computing ROI" << std::endl;
  197. //for ( int i = 0; i < m; ++i) {
  198. for ( std::vector< CvPoint >::size_type i = 0; i < ftlist.size(); ++i) {
  199. if( ftlist[i].x < x_min )
  200. x_min = ftlist[i].x;
  201. if( ftlist[i].y < y_min )
  202. y_min = ftlist[i].y;
  203. if( ftlist[i].x > x_max )
  204. x_max = ftlist[i].x;
  205. if( ftlist[i].y > y_max )
  206. y_max = ftlist[i].y;
  207. }
  208. if( m != 0 ) {
  209. ROI r(x_min, y_min, x_max-x_min, y_max-y_min, _width, _height);
  210. rv->push_back(r);
  211. }
  212. //#ifdef SIFT_TIMETRACKER
  213. __tt->ping_end(__ttc_roimerg);
  214. //#endif
  215. //#ifdef SIFT_TIMETRACKER
  216. __tt->ping_end(0);
  217. //#endif
  218. //#ifdef SIFT_TIMETRACKER
  219. __tt->print_to_stdout();
  220. //#endif
  221. std::cout << "SiftClassifier(classify): done ... returning '" << rv->size() << "' ROIs." << std::endl;
  222. return rv;
  223. }
  224. } // end namespace firevision