LFSiftPP.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /**
  2. * @file LFSiftPP.cpp
  3. * @brief Sift++ interface
  4. * @author Erik Rodner, Alexander Freytag
  5. * @date 11/19/2007
  6. */
  7. // STL includes
  8. #include <iostream>
  9. #include <sstream>
  10. // nice-core includes
  11. #include <core/basics/Exception.h>
  12. // #ifdef NICE_USELIB_ICE
  13. // #include <image_nonvis.h>
  14. // #endif
  15. // nice-vislearning includes
  16. #include "vislearning/features/localfeatures/LFSiftPP.h"
  17. //TODO move this to separate input or source folder
  18. #include "vislearning/features/localfeatures/sift.h"
  19. using namespace std;
  20. using namespace NICE;
  21. using namespace OBJREC;
  22. ///////////////////// ///////////////////// /////////////////////
  23. // CONSTRUCTORS / DESTRUCTORS
  24. ///////////////////// ///////////////////// /////////////////
  25. LFSiftPP::LFSiftPP() : LocalFeatureRepresentation ()
  26. {
  27. this->threshold = 0.0;
  28. this->edgeThreshold = 10.0;
  29. this->octaves = 6;
  30. this->first_octave = -1;
  31. this->levels = 3;
  32. this->minScale = 1;
  33. this->maxScale = 4;
  34. this->numScales = 10;
  35. this->numAngles = 6;
  36. this->descriptorAlignment = DALGIN_DETECTOR;
  37. this->normalizeFeature = false;
  38. }
  39. LFSiftPP::LFSiftPP( const Config * _conf )
  40. {
  41. this->initFromConfig( _conf );
  42. }
  43. LFSiftPP::~LFSiftPP()
  44. {
  45. }
  46. void LFSiftPP::initFromConfig(const NICE::Config * _conf, const std::string & _confSection)
  47. {
  48. this->threshold = _conf->gD(_confSection, "threshold", 0.0);
  49. this->edgeThreshold = _conf->gD(_confSection, "edge_threshold", 10.0);
  50. this->octaves = _conf->gI(_confSection, "octaves", 6);
  51. this->first_octave = _conf->gI(_confSection, "first_octave", -1);
  52. this->levels = _conf->gI(_confSection, "levels", 3);
  53. this->minScale = _conf->gD(_confSection, "min_scale", 1);
  54. this->maxScale = _conf->gD(_confSection, "max_scale", 4);
  55. this->numScales = _conf->gI(_confSection, "num_scales", 10);
  56. this->numAngles = _conf->gI(_confSection, "num_angles", 6 );
  57. std::string descriptorAlignment_s = _conf->gS(_confSection, "descriptor_alignment", "detector" );
  58. if ( descriptorAlignment_s == "detector" )
  59. this->descriptorAlignment = DALGIN_DETECTOR;
  60. else if ( descriptorAlignment_s == "multiple" )
  61. this->descriptorAlignment = DALIGN_MULTIPLE;
  62. else {
  63. fprintf (stderr, "LFSiftPP: descriptor alignment method unknown !\n");
  64. exit(-1);
  65. }
  66. this->normalizeFeature = _conf->gB(_confSection, "normalize_feature", false );
  67. //TODO check whether this os is still needed here.
  68. std::ostringstream os;
  69. os << "siftpp_" << "l" << levels << "_o"
  70. << octaves << "_m" << minScale << "_t"
  71. << threshold << "_e" << edgeThreshold;
  72. if ( ! normalizeFeature )
  73. os << "_nd";
  74. }
  75. ///////////////////// ///////////////////// /////////////////////
  76. // FEATURE STUFF
  77. ///////////////////// ///////////////////// /////////////////
  78. int LFSiftPP::getDescSize () const
  79. {
  80. return 128;
  81. }
  82. int LFSiftPP::extractFeatures ( const NICE::Image & img, VVector & features,
  83. VVector & positions ) const
  84. {
  85. int O = octaves ;
  86. int const S = levels ;
  87. int const omin = first_octave;
  88. float const sigman = .5 ;
  89. float const sigma0 = 1.6 * powf(2.0f, 1.0f / S) ;
  90. if (O < 1) {
  91. O = std::max
  92. (int
  93. (std::floor
  94. (log2
  95. (std::min(img.width(),img.height()))) - omin -3), 1) ;
  96. }
  97. const unsigned char *blockimg = (unsigned char*) img.getPixelPointer();
  98. if ( blockimg == NULL ) {
  99. fprintf (stderr, "FATAL ERROR: do not use subimages !!\n");
  100. exit(-1);
  101. }
  102. float *blockimgfl = new float[img.width() * img.height()];
  103. for ( int k = 0 ; k < img.width() * img.height() ; k++ )
  104. blockimgfl[k] = blockimg[k];
  105. VL::Sift sift( blockimgfl, img.width(), img.height(),
  106. sigman, sigma0, O, S, omin, -1, S+1) ;
  107. sift.process ( blockimgfl, img.width(), img.height() );
  108. // compute keypoints
  109. sift.detectKeypoints(threshold, edgeThreshold) ;
  110. const int descr_size = 128;
  111. VL::float_t *descr_pt = new VL::float_t [descr_size];
  112. VL::float_t angles[4] ;
  113. int keypointCount = 0;
  114. const int maxKeyPoints = std::numeric_limits<int>::max();
  115. NICE::Vector feature (descr_size);
  116. for( VL::Sift::KeypointsConstIter iter = sift.keypointsBegin() ;
  117. iter != sift.keypointsEnd() ; ++iter, keypointCount++ )
  118. {
  119. if ( keypointCount >= maxKeyPoints ) break;
  120. if ( descriptorAlignment == DALGIN_DETECTOR )
  121. {
  122. if ( iter->s < minScale ) continue;
  123. int nangles = sift.computeKeypointOrientations(angles, *iter);
  124. for ( int i = 0 ; i < nangles ; i++ )
  125. {
  126. sift.computeKeypointDescriptor ( descr_pt, *iter, angles[i] );
  127. for ( int j = 0 ; j < descr_size ; j++ )
  128. {
  129. if ( NICE::isNaN(descr_pt[j]) ) {
  130. fprintf (stderr, "Descriptor with NAN values !!\n");
  131. exit(-1);
  132. } else {
  133. feature[j] = descr_pt[j];
  134. }
  135. }
  136. NICE::Vector p (4);
  137. p[0] = iter->x;
  138. p[1] = iter->y;
  139. p[2] = iter->s;
  140. p[3] = angles[i];
  141. positions.push_back(p);
  142. if ( normalizeFeature )
  143. feature.normalizeL2();
  144. features.push_back ( feature );
  145. }
  146. } else if ( descriptorAlignment == DALIGN_MULTIPLE ) {
  147. double angle_step = 2 * M_PI / numAngles;
  148. double scale_step = (maxScale - minScale) / numScales;
  149. for ( int j = 0 ; j < numAngles ; j++ )
  150. {
  151. double scale = j * scale_step;
  152. for ( int i = 0 ; i < numAngles ; i++ )
  153. {
  154. double angle = angle_step * i;
  155. sift.computeKeypointDescriptor ( descr_pt, *iter, angle );
  156. for ( int j = 0 ; j < descr_size ; j++ )
  157. {
  158. if ( NICE::isNaN(descr_pt[j]) ) {
  159. fprintf (stderr, "Descriptor with NAN values !!\n");
  160. exit(-1);
  161. } else {
  162. feature[j] = descr_pt[j];
  163. }
  164. }
  165. NICE::Vector p (4);
  166. p[0] = iter->x;
  167. p[1] = iter->y;
  168. p[2] = iter->s;
  169. p[3] = angles[i];
  170. positions.push_back(p);
  171. if ( normalizeFeature )
  172. feature.normalizeL2();
  173. features.push_back ( feature );
  174. }
  175. }
  176. }
  177. }
  178. fprintf (stderr, "LFSiftpp::convert: Number of Keypoints = %d\n", keypointCount );
  179. delete [] blockimgfl;
  180. delete [] descr_pt;
  181. if ( keypointCount <= 0 )
  182. fprintf (stderr, "FATAL ERROR: no keypoints found !!\n");
  183. return 0;
  184. }
  185. void LFSiftPP::visualizeFeatures ( NICE::Image & mark,
  186. const VVector & positions,
  187. size_t color ) const
  188. {
  189. fthrow(Exception, "LFSiftPP::visualizeFeatures -- not yet implemented due to old ICE version.");
  190. // #ifdef NICE_USELIB_ICE
  191. // ice::Image mark_ice = ice::NewImg ( mark.width(),
  192. // mark.height(), 255 );
  193. // for ( size_t k = 0 ; k < positions.size() ; k++ )
  194. // {
  195. // const NICE::Vector & pos = positions[k];
  196. // ice::Matrix points ( 0, 2 );
  197. // const int size = 6;
  198. // points.Append ( ice::Vector(-size, -size) );
  199. // points.Append ( ice::Vector(-size, size) );
  200. // points.Append ( ice::Vector(size, size) );
  201. // points.Append ( ice::Vector(size, -size) );
  202. //
  203. // ice::Trafo tr;
  204. //
  205. // tr.Scale ( 0, 0, pos[2] );
  206. // tr.Rotate ( 0, 0, pos[3] );
  207. // tr.Shift ( pos[0], pos[1] );
  208. //
  209. // ice::TransformList(tr, points);
  210. //
  211. // for ( int j = 0 ; j < points.rows(); j++ )
  212. // {
  213. // if (points[j][0] < 0 )
  214. // points[j][0] = 0;
  215. // if (points[j][0] >= mark_ice->xsize)
  216. // points[j][0] = mark_ice->xsize - 1;
  217. // if (points[j][1] < 0 )
  218. // points[j][1] = 0;
  219. // if (points[j][1] >= mark_ice->ysize)
  220. // points[j][1] = mark_ice->ysize - 1;
  221. // }
  222. //
  223. // ice::DrawPolygon ( points, color, mark_ice );
  224. // }
  225. //
  226. // for ( unsigned int y = 0 ; y < mark.height(); y++ )
  227. // for ( unsigned int x = 0 ; x < mark.width(); x++ )
  228. // mark.setPixel(x,y, GetVal(mark_ice,x,y));
  229. // #else
  230. // cerr << "uses ice visualization, please install ice or change to NICE visualization" << endl;
  231. // #endif
  232. //TODO check this!
  233. }
  234. ///////////////////// INTERFACE PERSISTENT /////////////////////
  235. // interface specific methods for store and restore
  236. ///////////////////// INTERFACE PERSISTENT /////////////////////
  237. void LFSiftPP::restore ( std::istream & is, int format )
  238. {
  239. //delete everything we knew so far...
  240. this->clear();
  241. if ( is.good() )
  242. {
  243. std::string tmp;
  244. is >> tmp; //class name
  245. if ( ! this->isStartTag( tmp, "LFSiftPP" ) )
  246. {
  247. std::cerr << " WARNING - attempt to restore LFSiftPP, but start flag " << tmp << " does not match! Aborting... " << std::endl;
  248. throw;
  249. }
  250. bool b_endOfBlock ( false ) ;
  251. while ( !b_endOfBlock )
  252. {
  253. is >> tmp; // start of block
  254. if ( this->isEndTag( tmp, "LFSiftPP" ) )
  255. {
  256. b_endOfBlock = true;
  257. continue;
  258. }
  259. tmp = this->removeStartTag ( tmp );
  260. if ( tmp.compare("threshold") == 0 )
  261. {
  262. is >> this->threshold;
  263. is >> tmp; // end of block
  264. tmp = this->removeEndTag ( tmp );
  265. }
  266. else if ( tmp.compare("edgeThreshold") == 0 )
  267. {
  268. is >> this->edgeThreshold;
  269. is >> tmp; // end of block
  270. tmp = this->removeEndTag ( tmp );
  271. }
  272. else if ( tmp.compare("octaves") == 0 )
  273. {
  274. is >> this->octaves;
  275. is >> tmp; // end of block
  276. tmp = this->removeEndTag ( tmp );
  277. }
  278. else if ( tmp.compare("first_octave") == 0 )
  279. {
  280. is >> this->first_octave;
  281. is >> tmp; // end of block
  282. tmp = this->removeEndTag ( tmp );
  283. }
  284. else if ( tmp.compare("levels") == 0 )
  285. {
  286. is >> this->levels;
  287. is >> tmp; // end of block
  288. tmp = this->removeEndTag ( tmp );
  289. }
  290. else if ( tmp.compare("minScale") == 0 )
  291. {
  292. is >> this->minScale;
  293. is >> tmp; // end of block
  294. tmp = this->removeEndTag ( tmp );
  295. }
  296. else if ( tmp.compare("maxScale") == 0 )
  297. {
  298. is >> this->maxScale;
  299. is >> tmp; // end of block
  300. tmp = this->removeEndTag ( tmp );
  301. }
  302. else if ( tmp.compare("numScales") == 0 )
  303. {
  304. is >> this->numScales;
  305. is >> tmp; // end of block
  306. tmp = this->removeEndTag ( tmp );
  307. }
  308. else if ( tmp.compare("numAngles") == 0 )
  309. {
  310. is >> this->numAngles;
  311. is >> tmp; // end of block
  312. tmp = this->removeEndTag ( tmp );
  313. }
  314. else if ( tmp.compare("descriptorAlignment") == 0 )
  315. {
  316. unsigned int ui_descriptorAlignment;
  317. is >> ui_descriptorAlignment;
  318. this->descriptorAlignment = static_cast<DESCRIPTORALIGNMENT> ( ui_descriptorAlignment ) ;
  319. is >> tmp; // end of block
  320. tmp = this->removeEndTag ( tmp );
  321. }
  322. else if ( tmp.compare("normalizeFeature") == 0 )
  323. {
  324. is >> this->normalizeFeature;
  325. is >> tmp; // end of block
  326. tmp = this->removeEndTag ( tmp );
  327. }
  328. else
  329. {
  330. std::cerr << "WARNING -- unexpected LFSiftPP object -- " << tmp << " -- for restoration... aborting" << std::endl;
  331. throw;
  332. }
  333. }
  334. }
  335. else
  336. {
  337. std::cerr << "LFSiftPP::restore -- InStream not initialized - restoring not possible!" << std::endl;
  338. throw;
  339. }
  340. }
  341. void LFSiftPP::store ( std::ostream & os, int format ) const
  342. {
  343. if (os.good())
  344. {
  345. // show starting point
  346. os << this->createStartTag( "LFSiftPP" ) << std::endl;
  347. os << this->createStartTag( "threshold" ) << std::endl;
  348. os << this->threshold << std::endl;
  349. os << this->createEndTag( "threshold" ) << std::endl;
  350. os << this->createStartTag( "edgeThreshold" ) << std::endl;
  351. os << this->edgeThreshold << std::endl;
  352. os << this->createEndTag( "edgeThreshold" ) << std::endl;
  353. os << this->createStartTag( "octaves" ) << std::endl;
  354. os << this->octaves << std::endl;
  355. os << this->createEndTag( "octaves" ) << std::endl;
  356. os << this->createStartTag( "first_octave" ) << std::endl;
  357. os << this->first_octave << std::endl;
  358. os << this->createEndTag( "first_octave" ) << std::endl;
  359. os << this->createStartTag( "levels" ) << std::endl;
  360. os << this->levels << std::endl;
  361. os << this->createEndTag( "levels" ) << std::endl;
  362. os << this->createStartTag( "minScale" ) << std::endl;
  363. os << this->minScale << std::endl;
  364. os << this->createEndTag( "minScale" ) << std::endl;
  365. os << this->createStartTag( "maxScale" ) << std::endl;
  366. os << this->maxScale << std::endl;
  367. os << this->createEndTag( "maxScale" ) << std::endl;
  368. os << this->createStartTag( "numScales" ) << std::endl;
  369. os << this->numScales << std::endl;
  370. os << this->createEndTag( "numScales" ) << std::endl;
  371. os << this->createStartTag( "numAngles" ) << std::endl;
  372. os << this->numAngles << std::endl;
  373. os << this->createEndTag( "numAngles" ) << std::endl;
  374. os << this->createStartTag( "descriptorAlignment" ) << std::endl;
  375. os << this->descriptorAlignment << std::endl;
  376. os << this->createEndTag( "descriptorAlignment" ) << std::endl;
  377. os << this->createStartTag( "normalizeFeature" ) << std::endl;
  378. os << this->normalizeFeature << std::endl;
  379. os << this->createEndTag( "normalizeFeature" ) << std::endl;
  380. // done
  381. os << this->createEndTag( "LFSiftPP" ) << std::endl;
  382. }
  383. else
  384. {
  385. std::cerr << "OutStream not initialized - storing not possible!" << std::endl;
  386. }
  387. }
  388. void LFSiftPP::clear ()
  389. {
  390. }