LocalFeatureSift.cpp 9.0 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. //calling sift.process(.) already done in VL::Sift constructor, so omit the following process function
  137. //sift.process ( blockimgfl, img.width(), img.height() );
  138. sift.setMagnification ( magnif );
  139. sift.setNormalizeDescriptor ( normalizeFeature );
  140. const int descr_size = 128;
  141. VL::float_t *descr_pt = new VL::float_t [descr_size];
  142. VL::float_t angles[4] ;
  143. NICE::Vector feature (descr_size);
  144. NICE::Vector pos ( 4 );
  145. for ( vector< NICE::Vector >::iterator i = positions.begin();
  146. i != positions.end();)
  147. {
  148. const NICE::Vector & pos = *i;
  149. double x = pos[0];
  150. double y = pos[1];
  151. assert(pos[0] < img.width());
  152. assert(pos[1] < img.height());
  153. double s = pos[2];
  154. bool deleteFeature = false;
  155. VL::Sift::Keypoint kp = sift.getKeypoint (x,y,s);
  156. double angle = 0.0;
  157. if ( pos.size() < 4 )
  158. {
  159. int nangles = sift.computeKeypointOrientations(angles, kp);
  160. if ( nangles > 0 )
  161. {
  162. angle = angles[0];
  163. }
  164. else
  165. {
  166. if (deletemode)
  167. deleteFeature = true;
  168. else
  169. angle = 0;
  170. }
  171. }
  172. else
  173. {
  174. angle = pos[3];
  175. }
  176. if ( ! deleteFeature )
  177. {
  178. sift.computeKeypointDescriptor ( descr_pt, kp, angle );
  179. for ( int j = 0 ; j < descr_size ; j++ )
  180. // Umwandlung in Integer moegl.
  181. feature[j] = (integerValues ? (int)(512*descr_pt[j]) : descr_pt[j]);
  182. descriptors.push_back ( feature );
  183. i++;
  184. }
  185. else
  186. {
  187. i = positions.erase(i);
  188. }
  189. }
  190. delete [] blockimgfl;
  191. delete [] descr_pt;
  192. }
  193. #ifdef NICE_USELIB_CUDASIFT
  194. void LocalFeatureSift::withGPU(const NICE::Image& img, VVector& positions, VVector& descriptors) const
  195. {
  196. // fill the parameter for
  197. char* argv[] = {
  198. // First octave to detect DOG keypoints
  199. "-fo" , const_cast<char*> (StringTools::convertToString<int> (first_octave).c_str()),
  200. // Maximum number of Octaves
  201. "-no" , const_cast<char*> (StringTools::convertToString<int> (octaves).c_str()),
  202. // Number of DOG levels in an octave.
  203. "-d" , const_cast<char*> (StringTools::convertToString<int> (levels).c_str()),
  204. // Write unnormalized descriptor if specified.
  205. const_cast<char*> (normalizeFeature ? "" : "-unn"),
  206. // Descriptor grid size factor (magnif ??)
  207. "-dw" , const_cast<char*> (StringTools::convertToString<float> (magnif).c_str()),
  208. // verbose levels
  209. "-v", "0"
  210. };
  211. int argc = sizeof (argv) / sizeof (char*);
  212. // sift Instanz
  213. SiftGPU sift;
  214. // give parameter to sift
  215. sift.ParseParam (argc, argv);
  216. // check, whether siftgpu is full supported
  217. int support = sift.CreateContextGL();
  218. if( support != SiftGPU::SIFTGPU_FULL_SUPPORTED )
  219. throw runtime_error( "SiftGPU-support is not given by your device.");
  220. // set keypoints
  221. const int numberOfKeypoints = positions.size();
  222. SiftGPU::SiftKeypoint keys[numberOfKeypoints];
  223. // copy the NICEKeypoints into SiftKeypoints
  224. for (int i = 0; i < numberOfKeypoints; i++) {
  225. keys[i].x = positions[i][0];
  226. keys[i].y = positions[i][1];
  227. keys[i].s = positions[i][2];
  228. keys[i].o = positions[i][3];
  229. }
  230. sift.SetKeypointList (numberOfKeypoints, keys);
  231. // run SIFT
  232. const int imageWidth = img.width();
  233. const int imageHeight = img.height();
  234. const unsigned char* rawImageData = img.getPixelPointer();
  235. sift.RunSIFT (imageWidth, imageHeight, rawImageData, GL_LUMINANCE, GL_UNSIGNED_BYTE);
  236. // get descriptors
  237. const int descr_size = 128;
  238. const int numberOfDescriptors = sift.GetFeatureNum();
  239. float desc[descr_size * numberOfDescriptors];
  240. sift.GetFeatureVector (NULL, desc);
  241. Vector localDesc (descr_size);
  242. // copy the SiftDescriptors into NICEDescriptors
  243. for (int i = 0; i < numberOfDescriptors; i++) {
  244. for (int j = 0; j < descr_size; j++) {
  245. localDesc[j] = (integerValues ? (int) (512 * desc[i*descr_size+j]) : desc[i*descr_size+j]);
  246. }
  247. descriptors.push_back (localDesc);
  248. }
  249. }
  250. #endif