LFPatches.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /**
  2. * @file LFPatches.cpp
  3. * @brief simple patch based approach
  4. * @author Erik Rodner
  5. * @date 02/06/2008
  6. */
  7. #include <core/image/RectangleT.h>
  8. #include <core/image/ImageTools.h>
  9. #include <iostream>
  10. #include <sstream>
  11. #include "vislearning/features/localfeatures/LFPatches.h"
  12. #include "vislearning/features/localfeatures/IDRandomSampling.h"
  13. #include "vislearning/features/localfeatures/IDKLTSampling.h"
  14. #include "vislearning/features/localfeatures/IDSIFTSampling.h"
  15. #include "vislearning/image/ImagePyramid.h"
  16. using namespace OBJREC;
  17. using namespace std;
  18. using namespace NICE;
  19. void LFPatches::setDetector ( const int & _detectormode, const NICE::Config * conf)
  20. {
  21. if ( this->id != NULL )
  22. {
  23. delete this->id;
  24. this->id = NULL;
  25. }
  26. if (_detectormode == 0)
  27. {
  28. this->id = new IDRandomSampling(conf, this->numPatches);
  29. }
  30. else if (_detectormode == 1)
  31. {
  32. this->id = new IDKLTSampling(conf, this->numPatches);
  33. }
  34. else if (_detectormode == 2)
  35. {
  36. this->id = new IDSIFTSampling(conf);
  37. }
  38. else
  39. {
  40. this->id = new IDRandomSampling(conf, this->numPatches);
  41. }
  42. }
  43. void LFPatches::setNormalization( const std::string & _normalization_s)
  44. {
  45. if (_normalization_s == "n01")
  46. normalization = NORMALIZE_N01;
  47. else if (_normalization_s == "stddev")
  48. normalization = NORMALIZE_STDDEV;
  49. else if (_normalization_s == "mean")
  50. normalization = NORMALIZE_MEAN;
  51. else if (_normalization_s == "none")
  52. normalization = NORMALIZE_NONE;
  53. else
  54. {
  55. fprintf(stderr, "LFPatches::LFPatches: unknown normalization method\n");
  56. exit(-1);
  57. }
  58. }
  59. ///////////////////// ///////////////////// /////////////////////
  60. // CONSTRUCTORS / DESTRUCTORS
  61. ///////////////////// ///////////////////// /////////////////
  62. LFPatches::LFPatches()
  63. {
  64. this->numPatches = -1;
  65. this->xsize = 11;
  66. this->ysize = 11;
  67. this->maxLevels = 10;
  68. this->scaleSpacing = sqrt(sqrt(2));
  69. this->detectormode = 0;
  70. this->id = NULL;
  71. std::string normalization_s = "n01";
  72. this->setNormalization ( normalization_s );
  73. //TODO initialization useful here?
  74. srand(time(NULL));
  75. }
  76. LFPatches::LFPatches(const Config *conf, int _numPatches) :
  77. numPatches(_numPatches)
  78. {
  79. this->xsize = conf->gI("Patches", "xsize", 11);
  80. this->ysize = conf->gI("Patches", "ysize", 11);
  81. this->maxLevels = conf->gI("Patches", "levels", 10);
  82. this->scaleSpacing = conf->gD("Patches", "scale_spacing", sqrt(sqrt(2)));
  83. this->detectormode = conf->gI("Patches", "detector", 0);
  84. this->setDetector ( this->detectormode, conf );
  85. std::string normalization_s = conf->gS("Patches", "normalization", "n01");
  86. this->setNormalization ( normalization_s );
  87. srand(time(NULL));
  88. }
  89. LFPatches::~LFPatches()
  90. {
  91. if ( this->id != NULL )
  92. {
  93. delete this->id;
  94. this->id = NULL;
  95. }
  96. }
  97. ///////////////////// ///////////////////// /////////////////////
  98. // FEATURE STUFF
  99. ///////////////////// ///////////////////// //////////////////
  100. int LFPatches::getDescSize() const
  101. {
  102. return xsize * ysize;
  103. }
  104. int LFPatches::extractFeatures(const NICE::Image & img, VVector & features,
  105. VVector & positions) const
  106. {
  107. ImagePyramid imp(img, maxLevels, scaleSpacing, xsize, ysize);
  108. //imp.show();
  109. VVector positions_tmp;
  110. if(positions.size()<=0)
  111. {
  112. id->getRandomInterests(imp, positions_tmp,numPatches);
  113. }
  114. else
  115. {
  116. positions_tmp=positions;
  117. }
  118. correctPositions(imp, positions_tmp, positions);
  119. calcDescriptors(imp, positions, features);
  120. return features.size();
  121. }
  122. void LFPatches::correctPositions(const ImagePyramid & imp, VVector & positions,
  123. VVector & positions_corrected) const
  124. {
  125. positions_corrected.clear();
  126. int numlevels = imp.getNumLevels();
  127. for (size_t i = 0; i < positions.size(); i++)
  128. {
  129. const NICE::Vector & position = positions[i];
  130. if ((size_t) position[2] < numlevels)
  131. {
  132. const NICE::Image & img = imp.getLevel((size_t) position[2]);
  133. double xl, yl;
  134. imp.getLevelCoordinates(position[0], position[1],
  135. (size_t) position[2], xl, yl);
  136. int x = (int) xl;
  137. int y = (int) yl;
  138. x -= xsize / 2;
  139. y -= ysize / 2;
  140. if ((x >= 0) && (y >= 0) && (x <= img.width() - xsize) && (y
  141. <= img.height() - ysize))
  142. {
  143. NICE::Vector position_new(3);
  144. imp.getOriginalCoordinates(x, y,
  145. (size_t) position[2], position_new[0], position_new[1]);
  146. position_new[2] = position[2];
  147. positions_corrected.push_back(position_new);
  148. }
  149. }
  150. }
  151. }
  152. void LFPatches::calcDescriptors(const ImagePyramid & imp, VVector & positions,
  153. VVector & features) const
  154. {
  155. NICE::Vector desc(getDescSize());
  156. for (VVector::iterator i = positions.begin(); i != positions.end();)
  157. {
  158. bool deletePosition = false;
  159. if (calcDescriptor(imp, *i, desc) < 0)
  160. {
  161. deletePosition = true;
  162. }
  163. else
  164. {
  165. features.push_back(desc);
  166. }
  167. if (deletePosition)
  168. {
  169. i = positions.erase(i);
  170. }
  171. else
  172. {
  173. i++;
  174. }
  175. }
  176. }
  177. int LFPatches::calcDescriptor(const ImagePyramid & imp,
  178. const NICE::Vector & position, NICE::Vector & desc) const
  179. {
  180. const NICE::Image & img = imp.getLevel((size_t) position[2]);
  181. double xl, yl;
  182. imp.getLevelCoordinates(position[0], position[1], (uint) position[2], xl,
  183. yl);
  184. int x = (int) xl;
  185. int y = (int) yl;
  186. if ((x < 0) || (y < 0) || (x > img.width() - xsize) || (y > img.height()
  187. - ysize))
  188. {
  189. return -1;
  190. }
  191. double mean = 0.0;
  192. double stddev = 0.0;
  193. if (normalization != NORMALIZE_NONE)
  194. {
  195. // compute mean
  196. for (int yi = y; yi < y + ysize; yi++)
  197. for (int xi = x; xi < x + xsize; xi++)
  198. mean += img.getPixel(xi, yi);
  199. mean /= (xsize * ysize);
  200. if (normalization != NORMALIZE_MEAN)
  201. {
  202. // compute stddev
  203. stddev = 0.0;
  204. for (int yi = y; yi < y + ysize; yi++)
  205. for (int xi = x; xi < x + xsize; xi++)
  206. {
  207. double d = img.getPixel(xi, yi) - mean;
  208. stddev += d * d;
  209. }
  210. if (stddev < 10e-5)
  211. return -1;
  212. stddev /= xsize * ysize;
  213. stddev = sqrt(stddev);
  214. }
  215. }
  216. if (normalization == NORMALIZE_STDDEV)
  217. {
  218. // normalize pixel values
  219. int k = 0;
  220. for (int yi = y; yi < y + ysize; yi++)
  221. for (int xi = x; xi < x + xsize; xi++, k++)
  222. desc[k] = (img.getPixel(xi, yi) - mean) / stddev + mean;
  223. }
  224. else if (normalization == NORMALIZE_N01)
  225. {
  226. // normalize pixel values
  227. int k = 0;
  228. for (int yi = y; yi < y + ysize; yi++)
  229. for (int xi = x; xi < x + xsize; xi++, k++)
  230. desc[k] = (img.getPixel(xi, yi) - mean) / stddev;
  231. }
  232. else if (normalization == NORMALIZE_MEAN)
  233. {
  234. // normalize pixel values
  235. int k = 0;
  236. for (int yi = y; yi < y + ysize; yi++)
  237. for (int xi = x; xi < x + xsize; xi++, k++)
  238. desc[k] = (img.getPixel(xi, yi) - mean);
  239. }
  240. else
  241. {
  242. int k = 0;
  243. for (int yi = y; yi < y + ysize; yi++)
  244. for (int xi = x; xi < x + xsize; xi++, k++)
  245. desc[k] = img.getPixel(xi, yi);
  246. }
  247. return 0;
  248. }
  249. void LFPatches::visualizeFeatures(NICE::Image & mark,
  250. const VVector & positions, size_t color) const
  251. {
  252. for (size_t i = 0; i < positions.size(); i++)
  253. {
  254. const NICE::Vector & pos = positions[i];
  255. double s = pow(scaleSpacing, pos[2]);
  256. int x = (int) (pos[0]);
  257. int y = (int) (pos[1]);
  258. int w = (int) (s * xsize);
  259. int h = (int) (s * ysize);
  260. RectangleT<Ipp8u> rect(Coord(x, y), Coord(x + w, y + w));
  261. mark.draw(rect, (unsigned char) color);
  262. }
  263. }
  264. void LFPatches::visualize(NICE::Image & img, const NICE::Vector & feature) const
  265. {
  266. if (feature.size() != (size_t) xsize * ysize)
  267. {
  268. fprintf(stderr, "LFPatches::visualize implementation failure\n");
  269. exit(-1);
  270. }
  271. img.resize(xsize, ysize);
  272. double max = -numeric_limits<double>::max();
  273. double min = numeric_limits<double>::max();
  274. int k = 0;
  275. for (k = 0; k < xsize * ysize; k++)
  276. {
  277. if (feature[k] > max)
  278. max = feature[k];
  279. if (feature[k] < min)
  280. min = feature[k];
  281. }
  282. k = 0;
  283. for (int y = 0; y < ysize; y++)
  284. for (int x = 0; x < xsize; x++, k++)
  285. {
  286. double val = ((feature[k] - min) * 255 / (max - min));
  287. img.setPixel(x, y, (int) val);
  288. }
  289. }
  290. ///////////////////// INTERFACE PERSISTENT /////////////////////
  291. // interface specific methods for store and restore
  292. ///////////////////// INTERFACE PERSISTENT /////////////////////
  293. void LFPatches::restore ( std::istream & is, int format )
  294. {
  295. fthrow ( Exception, "LFPatches::restore not implemented yet." );
  296. //TODO
  297. }
  298. void LFPatches::store ( std::ostream & os, int format ) const
  299. {
  300. fthrow ( Exception, "LFPatches::store not implemented yet." );
  301. //TODO
  302. }
  303. void LFPatches::clear ()
  304. {
  305. if ( this->id != NULL )
  306. {
  307. delete this->id;
  308. this->id = NULL;
  309. }
  310. }