LocalFeatureSift.cpp 8.9 KB

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