LocalFeatureSift.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /**
  2. * @file LocalFeatureSift.cpp
  3. * @brief local feature with sift
  4. * @author Erik Rodner
  5. * @date 03/10/2012
  6. */
  7. #include "objrec/features/localfeatures/LocalFeatureSift.h"
  8. using namespace OBJREC;
  9. using namespace std;
  10. using namespace NICE;
  11. LocalFeatureSift::LocalFeatureSift( const Config *conf )
  12. {
  13. this->conf = conf;
  14. octaves = conf->gI("LFSiftPP", "octaves", 6);
  15. levels = conf->gI("LFSiftPP", "levels", 3);
  16. first_octave = conf->gI("LFSiftPP", "first_octave", -1);
  17. normalizeFeature = conf->gB("LFSiftPP", "normalize_feature", true );
  18. magnif = conf->gD("LFSiftPP", "magnif", 3 );
  19. deletemode = conf->gB("LFSiftPP", "deletemode", true );
  20. integerValues = conf->gB("LFSiftPP", "integer_values", true );
  21. #ifdef NICE_USELIB_CUDASIFT
  22. usegpu = conf->gB("LFSiftPP", "use_siftgpu", false );
  23. #else
  24. usegpu = false;
  25. #endif
  26. }
  27. LocalFeatureSift::~LocalFeatureSift()
  28. {
  29. }
  30. void LocalFeatureSift::sortPositions(VVector & positions) const
  31. {
  32. // < Key , Val >
  33. map<double, bool> scales;
  34. for ( vector< NICE::Vector >::iterator i = positions.begin();
  35. i != positions.end();i++)
  36. {
  37. const NICE::Vector & pos = *i;
  38. scales[pos[2]] = true;
  39. }
  40. VVector newpositions;
  41. map<double,bool>::iterator iter;
  42. for ( iter = scales.begin(); iter != scales.end(); ++iter )
  43. {
  44. for ( vector< NICE::Vector >::iterator i = positions.begin();
  45. i != positions.end();i++)
  46. {
  47. const NICE::Vector & pos = *i;
  48. if (pos[2] == iter->first)
  49. {
  50. newpositions.push_back(pos);
  51. }
  52. }
  53. }
  54. positions = newpositions;
  55. }
  56. void LocalFeatureSift::computeDesc( const NICE::Image & img, VVector & positions, VVector & descriptors ) const
  57. {
  58. if ( usegpu ) {
  59. try {
  60. #ifdef NICE_USELIB_CUDASIFT
  61. withGPU( img, positions, descriptors );
  62. #endif
  63. }
  64. catch ( runtime_error& rte ) {
  65. cerr << "[err] LocalFeatureSift: " << rte.what() << endl;
  66. clog << "[log] use SIFTPP implementation:" << endl;
  67. withPP( img, positions, descriptors );
  68. }
  69. }
  70. else {
  71. withPP( img, positions, descriptors );
  72. }
  73. }
  74. int LocalFeatureSift::getDescriptors ( const NICE::Image & img, VVector & positions, VVector & descriptors ) const
  75. {
  76. sortPositions(positions);
  77. computeDesc(img, positions, descriptors);
  78. return 0;
  79. }
  80. void LocalFeatureSift::visualizeFeatures ( NICE::Image & mark, const VVector & positions, size_t color ) const
  81. {
  82. /* TODO: switch to NICE instead of ICE
  83. ice::Image mark_ice = ice::NewImg ( mark.width(),
  84. mark.height(), 255 );
  85. for ( size_t k = 0 ; k < positions.size() ; k++ )
  86. {
  87. const NICE::Vector & pos = positions[k];
  88. ice::Matrix points ( 0, 2 );
  89. const int size = 6;
  90. points.Append ( ice::Vector(-size, -size) );
  91. points.Append ( ice::Vector(-size, size) );
  92. points.Append ( ice::Vector(size, size) );
  93. points.Append ( ice::Vector(size, -size) );
  94. ice::Trafo tr;
  95. tr.Scale ( 0, 0, pos[2] );
  96. tr.Rotate ( 0, 0, pos[3] );
  97. tr.Shift ( pos[0], pos[1] );
  98. ice::TransformList(tr, points);
  99. for ( int j = 0 ; j < points.rows(); j++ )
  100. {
  101. if (points[j][0] < 0 )
  102. points[j][0] = 0;
  103. if (points[j][0] >= mark_ice->xsize)
  104. points[j][0] = mark_ice->xsize - 1;
  105. if (points[j][1] < 0 )
  106. points[j][1] = 0;
  107. if (points[j][1] >= mark_ice->ysize)
  108. points[j][1] = mark_ice->ysize - 1;
  109. }
  110. ice::DrawPolygon ( points, color, mark_ice );
  111. }
  112. for ( unsigned int y = 0 ; y < mark.height(); y++ )
  113. for ( unsigned int x = 0 ; x < mark.width(); x++ )
  114. mark.setPixel(x,y, GetVal(mark_ice,x,y));*/
  115. }
  116. void LocalFeatureSift::withPP( const NICE::Image & img, VVector & positions, VVector & descriptors ) const
  117. {
  118. int O = octaves ;
  119. int const S = levels ;
  120. int const omin = first_octave;
  121. float const sigman = .5 ; //.5
  122. float const sigma0 = 1.6 * powf(2.0f, 1.0f / S) ;
  123. if (O < 1)
  124. {
  125. O = std::max(int(std::floor(log2
  126. (std::min(img.width(),img.height()))) - omin - 3), 1) ;
  127. }
  128. const unsigned char *blockimg = (unsigned char*) img.getPixelPointer();
  129. float *blockimgfl = new float[img.width() * img.height()];
  130. for ( int k = 0 ; k < img.width() * img.height() ; k++ )
  131. blockimgfl[k] = blockimg[k];
  132. VL::Sift sift( blockimgfl, img.width(), img.height(),
  133. sigman, sigma0, O, S, omin, -1, S+1) ;
  134. sift.process ( blockimgfl, img.width(), img.height() );
  135. sift.setMagnification ( magnif );
  136. sift.setNormalizeDescriptor ( normalizeFeature );
  137. const int descr_size = 128;
  138. VL::float_t *descr_pt = new VL::float_t [descr_size];
  139. VL::float_t angles[4] ;
  140. NICE::Vector feature (descr_size);
  141. NICE::Vector pos ( 4 );
  142. for ( vector< NICE::Vector >::iterator i = positions.begin();
  143. i != positions.end();)
  144. {
  145. const NICE::Vector & pos = *i;
  146. double x = pos[0];
  147. double y = pos[1];
  148. assert(pos[0] < img.width());
  149. assert(pos[1] < img.height());
  150. double s = pos[2];
  151. bool deleteFeature = false;
  152. VL::Sift::Keypoint kp = sift.getKeypoint (x,y,s);
  153. double angle = 0.0;
  154. if ( pos.size() < 4 )
  155. {
  156. int nangles = sift.computeKeypointOrientations(angles, kp);
  157. if ( nangles > 0 )
  158. {
  159. angle = angles[0];
  160. }
  161. else
  162. {
  163. if (deletemode)
  164. deleteFeature = true;
  165. else
  166. angle = 0;
  167. }
  168. }
  169. else
  170. {
  171. angle = pos[3];
  172. }
  173. if ( ! deleteFeature )
  174. {
  175. sift.computeKeypointDescriptor ( descr_pt, kp, angle );
  176. for ( int j = 0 ; j < descr_size ; j++ )
  177. // Umwandlung in Integer moegl.
  178. feature[j] = (integerValues ? (int)(512*descr_pt[j]) : descr_pt[j]);
  179. descriptors.push_back ( feature );
  180. i++;
  181. }
  182. else
  183. {
  184. i = positions.erase(i);
  185. }
  186. }
  187. delete [] blockimgfl;
  188. delete [] descr_pt;
  189. }
  190. #ifdef NICE_USELIB_CUDASIFT
  191. void LocalFeatureSift::withGPU(const NICE::Image& img, OBJREC::VVector& positions, OBJREC::VVector& descriptors) const
  192. {
  193. // fill the parameter for
  194. char* argv[] = {
  195. // First octave to detect DOG keypoints
  196. "-fo" , const_cast<char*> (StringTools::convertToString<int> (first_octave).c_str()),
  197. // Maximum number of Octaves
  198. "-no" , const_cast<char*> (StringTools::convertToString<int> (octaves).c_str()),
  199. // Number of DOG levels in an octave.
  200. "-d" , const_cast<char*> (StringTools::convertToString<int> (levels).c_str()),
  201. // Write unnormalized descriptor if specified.
  202. const_cast<char*> (normalizeFeature ? "" : "-unn"),
  203. // Descriptor grid size factor (magnif ??)
  204. "-dw" , const_cast<char*> (StringTools::convertToString<float> (magnif).c_str()),
  205. // verbose levels
  206. "-v", "0"
  207. };
  208. int argc = sizeof (argv) / sizeof (char*);
  209. // sift Instanz
  210. SiftGPU sift;
  211. // give parameter to sift
  212. sift.ParseParam (argc, argv);
  213. // check, whether siftgpu is full supported
  214. int support = sift.CreateContextGL();
  215. if( support != SiftGPU::SIFTGPU_FULL_SUPPORTED )
  216. throw runtime_error( "SiftGPU-support is not given by your device.");
  217. // set keypoints
  218. const int numberOfKeypoints = positions.size();
  219. SiftGPU::SiftKeypoint keys[numberOfKeypoints];
  220. // copy the NICEKeypoints into SiftKeypoints
  221. for (int i = 0; i < numberOfKeypoints; i++) {
  222. keys[i].x = positions[i][0];
  223. keys[i].y = positions[i][1];
  224. keys[i].s = positions[i][2];
  225. keys[i].o = positions[i][3];
  226. }
  227. sift.SetKeypointList (numberOfKeypoints, keys);
  228. // run SIFT
  229. const int imageWidth = img.width();
  230. const int imageHeight = img.height();
  231. const unsigned char* rawImageData = img.getPixelPointer();
  232. sift.RunSIFT (imageWidth, imageHeight, rawImageData, GL_LUMINANCE, GL_UNSIGNED_BYTE);
  233. // get descriptors
  234. const int descr_size = 128;
  235. const int numberOfDescriptors = sift.GetFeatureNum();
  236. float desc[descr_size * numberOfDescriptors];
  237. sift.GetFeatureVector (NULL, desc);
  238. Vector localDesc (descr_size);
  239. // copy the SiftDescriptors into NICEDescriptors
  240. for (int i = 0; i < numberOfDescriptors; i++) {
  241. for (int j = 0; j < descr_size; j++) {
  242. localDesc[j] = (integerValues ? (int) (512 * desc[i*descr_size+j]) : desc[i*descr_size+j]);
  243. }
  244. descriptors.push_back (localDesc);
  245. }
  246. }
  247. #endif