LocalizationResult.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /**
  2. * @file LocalizationResult.cpp
  3. * @brief Localization result, what else?
  4. * @author Erik Rodner
  5. * @date 02/13/2008
  6. */
  7. #include <vislearning/nice_nonvis.h>
  8. #include <iostream>
  9. #include <core/image/LineT.h>
  10. #include "vislearning/cbaselib/LocalizationResult.h"
  11. #include "core/basics/StringTools.h"
  12. using namespace OBJREC;
  13. using namespace std;
  14. using namespace NICE;
  15. /******** SingleLocalizationResult ********/
  16. SingleLocalizationResult::SingleLocalizationResult ( ClassificationResult *_r, const NICE::Region & _reg, int _controlPoints )
  17. : controlPoints(_controlPoints), hasRegionInformation_bool(true), reg(_reg), r(_r)
  18. {
  19. reg.getRect(xi,yi,xa,ya);
  20. }
  21. SingleLocalizationResult::SingleLocalizationResult ( ClassificationResult *_r, int _xi, int _yi, int _xa, int _ya )
  22. : controlPoints(4), xi(_xi), yi(_yi), xa(_xa), ya(_ya), hasRegionInformation_bool(true), r(_r)
  23. {
  24. // reg.add (xi,yi,xa,ya);
  25. // this might lead to problems...in general the current Region representation is awful !
  26. }
  27. double SingleLocalizationResult::getBBOverlapMeasureMin ( const SingleLocalizationResult & y ) const
  28. {
  29. double measure = 0.0;
  30. int xxi, xyi, xxa, xya;
  31. int yxi, yyi, yxa, yya;
  32. getBoundingBox ( xxi, xyi, xxa, xya );
  33. y.getBoundingBox ( yxi, yyi, yxa, yya );
  34. int mxi = ( xxi > yxi ) ? xxi : yxi;
  35. int myi = ( xyi > yyi ) ? xyi : yyi;
  36. int mxa = ( xxa < yxa ) ? xxa : yxa;
  37. int mya = ( xya < yya ) ? xya : yya;
  38. int iw = mxa - mxi + 1;
  39. int ih = mya - myi + 1;
  40. if ( (iw > 0) && (ih > 0) )
  41. {
  42. // if iw>0 & ih>0
  43. double A = (xxa - xxi + 1)*(xya - xyi + 1);
  44. double B = (yxa - yxi + 1)*(yya - yyi + 1);
  45. double overlap = A < B ? A : B;
  46. measure = iw*ih / overlap;
  47. }
  48. return measure;
  49. }
  50. double SingleLocalizationResult::getBBOverlapMeasure ( const SingleLocalizationResult & y ) const
  51. {
  52. double measure = 0.0;
  53. int xxi, xyi, xxa, xya;
  54. int yxi, yyi, yxa, yya;
  55. getBoundingBox ( xxi, xyi, xxa, xya );
  56. y.getBoundingBox ( yxi, yyi, yxa, yya );
  57. int mxi = ( xxi > yxi ) ? xxi : yxi;
  58. int myi = ( xyi > yyi ) ? xyi : yyi;
  59. int mxa = ( xxa < yxa ) ? xxa : yxa;
  60. int mya = ( xya < yya ) ? xya : yya;
  61. int iw = mxa - mxi + 1;
  62. int ih = mya - myi + 1;
  63. if ( (iw > 0) && (ih > 0) )
  64. {
  65. // if iw>0 & ih>0
  66. double overlap = (xxa - xxi + 1)*(xya - xyi + 1) +
  67. (yxa - yxi + 1)*(yya - yyi + 1) -
  68. iw*ih;
  69. measure = iw*ih / overlap;
  70. }
  71. return measure;
  72. }
  73. void SingleLocalizationResult::getBoundingBox ( int & _xi, int & _yi, int & _xa, int & _ya ) const
  74. {
  75. _xi = xi;
  76. _yi = yi;
  77. _xa = xa;
  78. _ya = ya;
  79. }
  80. void SingleLocalizationResult::getBoundingBox ( RectT<int> & rectangle ) const
  81. {
  82. rectangle = RectT<int> ( CoordT<int> ( xi, yi ), CoordT<int> ( xa, ya ) );
  83. }
  84. void SingleLocalizationResult::getCentroid ( double & x, double & y ) const
  85. {
  86. reg.getCentroid ( x, y );
  87. }
  88. SingleLocalizationResult::~SingleLocalizationResult ()
  89. {
  90. if ( r != NULL )
  91. delete r;
  92. }
  93. /******** LocalizationResult *********/
  94. LocalizationResult::LocalizationResult ( int xsize, int ysize ) : cn(NULL)
  95. {
  96. hasLabeledImage = false;
  97. this->xsize = xsize;
  98. this->ysize = ysize;
  99. }
  100. LocalizationResult::LocalizationResult ( const ClassNames *_cn, int xsize, int ysize ) : cn(_cn)
  101. {
  102. hasLabeledImage = false;
  103. this->xsize = xsize;
  104. this->ysize = ysize;
  105. }
  106. LocalizationResult::~LocalizationResult ()
  107. {
  108. for ( iterator k = begin(); k != end() ; k++ )
  109. {
  110. SingleLocalizationResult *slr = *k;
  111. delete slr;
  112. }
  113. }
  114. #undef DEBUG_LOCALIZATIONREAD
  115. LocalizationResult::LocalizationResult ( const ClassNames *_cn, const NICE::Image & img, int classno ) : cn(_cn)
  116. {
  117. const int t = 200; // FIXME
  118. NICE::Region reg;
  119. #ifdef DEBUG_LOCALIZATIONREAD
  120. NICE::Image imgo (img);
  121. imgo.set(0);
  122. #endif
  123. this->xsize = img.width();
  124. this->ysize = img.height();
  125. for ( int y = 0 ; y < img.height(); y++ )
  126. for ( int x = 0 ; x < img.width(); x++ )
  127. {
  128. // refactor-nice.pl: check this substitution
  129. // old: if ( GetVal(img, x, y) < t )
  130. if ( img.getPixel(x,y) < t )
  131. {
  132. #ifdef DEBUG_LOCALIZATIONREAD
  133. imgo.setPixel(x,y,1);
  134. #endif
  135. reg.add ( x, y );
  136. }
  137. }
  138. #ifdef DEBUG_LOCALIZATIONREAD
  139. NICE::showImageOverlay ( imgo, imgo );
  140. #endif
  141. ClassificationResult *r = new ClassificationResult (classno, 1.0, _cn->getMaxClassno());
  142. push_back ( new SingleLocalizationResult ( r, reg ) );
  143. hasLabeledImage = false;
  144. }
  145. LocalizationResult::LocalizationResult ( const ClassNames *_cn, const NICE::ColorImage & img) : cn(_cn)
  146. {
  147. map<int, NICE::Region> regions;
  148. xsize = img.width();
  149. ysize = img.height();
  150. #ifdef DEBUG_LOCALIZATIONREAD
  151. NICE::showImage ( img );
  152. NICE::Image imgo (xsize,ysize);
  153. imgo.set(0);
  154. #endif
  155. for ( int y = 0 ; y < ysize ; y++ )
  156. for ( int x = 0 ; x < xsize ; x++ )
  157. {
  158. int r = img.getPixel(x,y,0);
  159. int g = img.getPixel(x,y,1);
  160. int b = img.getPixel(x,y,2);
  161. int classno;
  162. _cn->getClassnoFromColor ( classno, r, g, b );
  163. if ( classno >= 0 )
  164. regions[classno].add(x,y);
  165. #ifdef DEBUG_LOCALIZATIONREAD
  166. imgo.setPixel(x,y,classno);
  167. #endif
  168. }
  169. for ( map<int, NICE::Region>::const_iterator j = regions.begin();
  170. j != regions.end();
  171. j++ )
  172. {
  173. int classno = j->first;
  174. ClassificationResult *r = new ClassificationResult (classno, 1.0, _cn->getMaxClassno());
  175. push_back ( new SingleLocalizationResult ( r, j->second ) );
  176. }
  177. hasLabeledImage = false;
  178. }
  179. void LocalizationResult::restore (istream & is, int format)
  180. {
  181. if ( format == FILEFORMAT_PASCAL2006_RESULT )
  182. {
  183. while ( ! is.eof() )
  184. {
  185. double score;
  186. int xi, yi, xa, ya;
  187. // refactor-nice.pl: check this substitution
  188. // old: string classname;
  189. std::string classname;
  190. if ( ! (is >> classname) ) break;
  191. if ( ! (is >> score) ) break;
  192. if ( ! (is >> xi) ) break;
  193. if ( ! (is >> yi) ) break;
  194. if ( ! (is >> xa) ) break;
  195. if ( ! (is >> ya) ) break;
  196. ClassificationResult *r = new ClassificationResult ( cn->classno(classname), score, cn->getMaxClassno() );
  197. SingleLocalizationResult *sr = new SingleLocalizationResult ( r, xi, yi, xa, ya );
  198. push_back ( sr );
  199. }
  200. } else if ( format == FILEFORMAT_PASCAL2006_GROUNDTRUTH ) {
  201. #if 0
  202. /* # Details for object 1 ("PAScat")
  203. Original label for object 1 "PAScat" : "PAScat"
  204. Bounding box for object 1 "PAScat" (Xmin, Ymin) - (Xmax, Ymax) : (11, 135) - (333, 410) */
  205. // refactor-nice.pl: check this substitution
  206. // old: string word;
  207. std::string word;
  208. while ( ! is.eof() )
  209. {
  210. if ( ! (is >> word) ) break;
  211. if ( word != "Bounding" ) continue;
  212. char line[1024];
  213. is.getline (line, 1024);
  214. vector<string> submatches;
  215. bool result = StringTools::regexMatch ( line, "box for object ([:digit]+) \"([:alpha:]+)\" (Xmin, Ymin) - (Xmax, Ymax) : (([:digit:]+) *, *([:digit:]+)) *: *(([:digit:]+) *, *([:digit:]+))", submatches );
  216. cerr << "string: " << line << endl;
  217. for ( vector<string>::const_iterator i = submatches.begin(); i != submatches.end(); i++ )
  218. cerr << "submatch " << *i << endl;
  219. exit(-1);
  220. }
  221. #endif
  222. } else if ( format == FILEFORMAT_POLYGON ) {
  223. // This is limited to bounding boxes ...sorry
  224. while (! is.eof()) {
  225. #define USE_CALTECH101_POLYGON_FORMAT
  226. #ifdef USE_CALTECH101_POLYGON_FORMAT
  227. std::string filename;
  228. if ( !(is >> filename) ) break;
  229. #endif
  230. std::string classname;
  231. if ( !(is >> classname) ) break;
  232. const double score = 1.0;
  233. int classno = cn->classnoFromText(classname);
  234. uint polygon_points;
  235. if ( !(is >> polygon_points) ) break;
  236. int xi = std::numeric_limits<int>::max();
  237. int xa = - std::numeric_limits<int>::max();
  238. int yi = std::numeric_limits<int>::max();
  239. int ya = - std::numeric_limits<int>::max();
  240. for ( uint i = 0 ; i < polygon_points ; i++ )
  241. {
  242. double x,y;
  243. if ( !(is >> x) ) break;
  244. if ( !(is >> y) ) break;
  245. if ( x < xi ) xi = x;
  246. if ( x > xa ) xa = x;
  247. if ( y < yi ) yi = y;
  248. if ( y > ya ) ya = y;
  249. }
  250. if ( classno >= 0 ) {
  251. ClassificationResult *r = new ClassificationResult ( classno, score, cn->getMaxClassno() );
  252. SingleLocalizationResult *sr = new SingleLocalizationResult ( r, xi, yi, xa, ya );
  253. push_back ( sr );
  254. }
  255. }
  256. //sortEmpricalDepth();
  257. } else {
  258. fthrow(IOException, "LocalizationResult::restore: file format not yet supported !");
  259. }
  260. }
  261. void LocalizationResult::store (ostream & os, int format) const
  262. {
  263. if ( format == FILEFORMAT_PASCAL2006_RESULT )
  264. {
  265. for ( const_iterator i = begin(); i != end(); i++ )
  266. {
  267. const SingleLocalizationResult *sr = *i;
  268. const ClassificationResult *r = sr->r;
  269. int classno = r->classno;
  270. double score = r->scores.get(classno);
  271. int xi, yi, xa, ya;
  272. sr->getBoundingBox ( xi, yi, xa, ya );
  273. os << cn->text(r->classno) << " " << score << " "
  274. << xi << " "
  275. << yi << " "
  276. << xa << " "
  277. << ya << " " << endl;
  278. }
  279. } else {
  280. fprintf (stderr, "LocalizationResult::store: file format not yet supported !\n");
  281. exit(-1);
  282. }
  283. }
  284. void LocalizationResult::clear ()
  285. {
  286. for ( iterator k = begin(); k != end() ; k++ )
  287. {
  288. SingleLocalizationResult *slr = *k;
  289. delete slr;
  290. }
  291. vector<SingleLocalizationResult *>::clear();
  292. hasLabeledImage = false;
  293. }
  294. /** returns whether the depth of x is smaller than that of y
  295. !!! no transitivity !!! */
  296. bool depthCompare ( const SingleLocalizationResult *x, const SingleLocalizationResult *y )
  297. {
  298. /** According to the LabelMe paper of Torralba et al., Murphy */
  299. const NICE::Region & rx = x->getRegion();
  300. const NICE::Region & ry = y->getRegion();
  301. NICE::Region intersect;
  302. intersect.setIntersection ( rx, ry );
  303. int ax = rx.size();
  304. int ay = ry.size();
  305. int is = intersect.size();
  306. if ( is == 0 )
  307. {
  308. int nx = x->getControlPoints();
  309. int ny = y->getControlPoints();
  310. return ( nx > ny );
  311. } else {
  312. double ratx = (double)is / ax;
  313. double raty = (double)is / ay;
  314. return ( ratx > raty );
  315. }
  316. }
  317. bool confidenceCompare ( const SingleLocalizationResult *x, const SingleLocalizationResult *y )
  318. {
  319. return ( x->r->confidence() > y->r->confidence() );
  320. }
  321. void LocalizationResult::sortDescendingConfidence()
  322. {
  323. sort ( begin(), end(), confidenceCompare );
  324. }
  325. void LocalizationResult::sortEmpricalDepth()
  326. {
  327. sort ( begin(), end(), depthCompare );
  328. }
  329. void LocalizationResult::calcLabeledImage ( NICE::Image & mark, int backgroundClassNo ) const
  330. {
  331. mark.set(backgroundClassNo);
  332. fprintf (stderr, "LocalizationResult: calcLabeledImage %zd\n", size() );
  333. for ( int y = 0 ; y < mark.height(); y++ )
  334. for ( int x = 0 ; x < mark.width(); x++ )
  335. {
  336. for ( LocalizationResult::const_iterator k = begin(); k != end() ; k++ )
  337. {
  338. SingleLocalizationResult *slr = *k;
  339. const NICE::Region & r = slr->getRegion();
  340. if ( r.inside(x,y) ) {
  341. mark.setPixel(x,y,slr->r->classno);
  342. break;
  343. }
  344. }
  345. }
  346. }
  347. void LocalizationResult::getLabeledImageCache ( NICE::Image & mark ) const
  348. {
  349. assert ( hasLabeledImage );
  350. labeledImage->copyFrom ( mark );
  351. }
  352. void LocalizationResult::setMap ( const NICE::Image & _labeledImage )
  353. {
  354. labeledImage = new Image( _labeledImage );
  355. hasLabeledImage = true;
  356. }
  357. void drawOrthoLine ( NICE::ColorImage & img,
  358. int x1, int y1, int x2, int y2,
  359. int width, int sign,
  360. int r,
  361. int g,
  362. int b )
  363. {
  364. int xi = x1; int yi = y1;
  365. int xa = x2; int ya = y2;
  366. for ( int i = 0 ; i < width; i++ )
  367. {
  368. if ( yi == ya ) {
  369. yi = yi + sign;
  370. ya = ya + sign;
  371. } else if ( xi == xa ) {
  372. xi = xi + sign;
  373. xa = xa + sign;
  374. } else {
  375. assert ( 0 == 1 );
  376. }
  377. if ( (xi>=0) && (yi>=0) && (xa<=img.width())
  378. && (ya<=img.height()) )
  379. {
  380. NICE::Line l ( Coord(xi, yi), Coord(xa, ya) );
  381. img.draw( l, NICE::Color(r, g, b) );
  382. }
  383. }
  384. }
  385. void LocalizationResult::displayBoxes ( NICE::ColorImage & img, const ClassNames *cn,
  386. bool display_confidence, bool invert, int width ) const
  387. {
  388. for ( LocalizationResult::const_iterator k = begin(); k != end() ; k++ )
  389. {
  390. SingleLocalizationResult *slr = *k;
  391. int xi, yi, xa, ya;
  392. slr->getBoundingBox ( xi, yi, xa, ya );
  393. int classno = (slr->r == NULL ) ? 0 : slr->r->classno;
  394. int r,g,b;
  395. if ( cn != NULL ) {
  396. cn->getRGBColor ( classno, r, g, b );
  397. } else {
  398. r = 255;
  399. g = 0;
  400. b = 0;
  401. }
  402. if ( invert ) {
  403. r = 255 - r;
  404. g = 255 - g;
  405. b = 255 - b;
  406. }
  407. if ( display_confidence && (cn != NULL)) {
  408. std::string name = cn->text(classno);
  409. char caption[1024];
  410. sprintf ( caption, "%3.2lf %s", slr->r->confidence(), name.c_str() );
  411. // refactor-nice.pl: check this substitution
  412. // old: Text(caption, xi, yi, r, 0, img.RedImage());
  413. // REFACTOR-FIXME Unable to map this statement
  414. // refactor-nice.pl: check this substitution
  415. // old: Text(caption, xi, yi, g, 0, img.GreenImage());
  416. // REFACTOR-FIXME Unable to map this statement
  417. // refactor-nice.pl: check this substitution
  418. // old: Text(caption, xi, yi, b, 0, img.BlueImage());
  419. // REFACTOR-FIXME Unable to map this statement
  420. }
  421. drawOrthoLine ( img, xi-width, yi, xa+width, yi, width, -1, r, g, b );
  422. drawOrthoLine ( img, xa, yi, xa, ya, width, +1, r, g, b );
  423. drawOrthoLine ( img, xa+width, ya, xi-width, ya, width, +1, r, g, b );
  424. drawOrthoLine ( img, xi, ya, xi, yi, width, -1, r, g, b );
  425. }
  426. }