ClassNames.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /**
  2. * @file ClassNames.cpp
  3. * @brief simple interface for class name confusion
  4. * @author Erik Rodner
  5. * @date 02/08/2008
  6. */
  7. #include "core/image/ImageT.h"
  8. #include "core/vector/VectorT.h"
  9. #include "core/vector/MatrixT.h"
  10. #include <iostream>
  11. #include <algorithm>
  12. #include <string>
  13. #include <functional>
  14. #include <assert.h>
  15. #include "vislearning/cbaselib/ClassNames.h"
  16. #include "core/basics/StringTools.h"
  17. #include "vislearning/baselib/ICETools.h"
  18. using namespace OBJREC;
  19. using namespace std;
  20. using namespace NICE;
  21. ClassNames::ClassNames()
  22. {
  23. maxClassNo = 0;
  24. }
  25. ClassNames::ClassNames ( const ClassNames & cn,
  26. const std::string & classselection )
  27. {
  28. std::set<int> selection;
  29. cn.getSelection ( classselection, selection );
  30. maxClassNo = 0;
  31. store ( cerr );
  32. for ( map<string, string>::const_iterator i = cn.tbl_code_text.begin();
  33. i != cn.tbl_code_text.end();
  34. i++ )
  35. {
  36. const std::string & classname = i->second;
  37. std::string code = i->first;
  38. if ( cn.tbl_code_classno.find(code) == cn.tbl_code_classno.end() )
  39. {
  40. fprintf (stderr, "class %s excluded in base classnames\n", code.c_str() );
  41. continue;
  42. }
  43. int classno = cn.classno(code);
  44. if ( selection.find(classno) != selection.end() )
  45. {
  46. addClass( classno, code, classname );
  47. if ( classno > maxClassNo ) maxClassNo = classno;
  48. #ifdef DEBUG_ClassNames
  49. fprintf (stderr, "class %s (%d) inherited\n", code.c_str(), classno );
  50. #endif
  51. } else {
  52. #ifdef DEBUG_ClassNames
  53. fprintf (stderr, "class %s (%d) excluded in selection\n", code.c_str(), classno );
  54. #endif
  55. }
  56. }
  57. }
  58. ClassNames::ClassNames ( const ClassNames & cn )
  59. : tbl_code_text(cn.tbl_code_text), tbl_text_code(cn.tbl_text_code),
  60. tbl_classno_code(cn.tbl_classno_code), tbl_code_classno(cn.tbl_code_classno),
  61. tbl_color_classno(tbl_color_classno), tbl_classno_color(cn.tbl_classno_color), maxClassNo(cn.maxClassNo)
  62. {
  63. }
  64. ClassNames::~ClassNames()
  65. {
  66. }
  67. int ClassNames::classnoFromText ( std::string text ) const
  68. {
  69. map<string, string>::const_iterator j = tbl_text_code.find(text);
  70. if ( j == tbl_text_code.end() ) return -1;
  71. map<string, int>::const_iterator jj = tbl_code_classno.find(j->second);
  72. if ( jj == tbl_code_classno.end() ) return -1;
  73. return jj->second;
  74. }
  75. void ClassNames::getSelection ( const std::string & classselection,
  76. std::set<int> & classnos ) const
  77. {
  78. if ( classselection.size() <= 0 ) return;
  79. std::vector<string> classlist;
  80. StringTools::split ( classselection, ',', classlist );
  81. if ( classlist.size() <= 0 )
  82. {
  83. fprintf (stderr, "FATAL ERROR: wrong format for classselection\n");
  84. exit(-1);
  85. } else if ( classlist[0] == "*" )
  86. {
  87. map<string, bool> forbidden_classes;
  88. for ( size_t k = 1 ; k < classlist.size() ; k++ )
  89. if ( classlist[k].substr(0,1) == "-" )
  90. {
  91. std::string f_class = classlist[k].substr(1);
  92. #if defined DEBUG_ClassNames
  93. fprintf (stderr, "ClassNames: class %s excluded !\n", f_class.c_str() );
  94. #endif
  95. forbidden_classes[ f_class ] = true;
  96. } else {
  97. fprintf (stderr, "FATAL ERROR: wrong format for classselection: *,-class0,class1,...\n");
  98. exit(-1);
  99. }
  100. for ( map<int, string>::const_iterator i = tbl_classno_code.begin();
  101. i != tbl_classno_code.end();
  102. i++ )
  103. {
  104. int myclassno = i->first;
  105. const std::string & classname = text(myclassno);
  106. if ( forbidden_classes.find(classname) != forbidden_classes.end() )
  107. continue;
  108. classnos.insert ( myclassno );
  109. }
  110. } else {
  111. for ( vector<string>::const_iterator i = classlist.begin();
  112. i != classlist.end();
  113. i++ )
  114. {
  115. const std::string & classname = *i;
  116. map<string, string>::const_iterator j = tbl_text_code.find(classname);
  117. if ( j == tbl_text_code.end() )
  118. {
  119. fprintf (stderr, "ClassNames: FATAL ERROR This is not a selection of a subset: %s [%s]\n",
  120. classname.c_str(), classselection.c_str());
  121. exit(-1);
  122. }
  123. const std::string & code = j->second;
  124. int myclassno = classno (code);
  125. if ( myclassno < 0 ) {
  126. fprintf (stderr, "ClassNames: FATAL ERROR This is not a selection of a subset\n");
  127. exit(-1);
  128. }
  129. classnos.insert ( myclassno );
  130. }
  131. }
  132. }
  133. std::string ClassNames::text ( int classno ) const
  134. {
  135. map<string, string>::const_iterator i =
  136. tbl_code_text.find ( code(classno) );
  137. if ( i == tbl_code_text.end() )
  138. {
  139. fprintf (stderr, "ClassNames: no name found for classno %d\n", classno );
  140. return "unknown";
  141. } else {
  142. return i->second;
  143. }
  144. }
  145. std::string ClassNames::code ( int classno ) const
  146. {
  147. map<int, string>::const_iterator i =
  148. tbl_classno_code.find ( classno );
  149. if ( i == tbl_classno_code.end() )
  150. {
  151. fprintf (stderr, "ClassNames: no code found for classno %d\n", classno );
  152. return "unknown";
  153. } else {
  154. return i->second;
  155. }
  156. }
  157. int ClassNames::classno ( std::string code ) const
  158. {
  159. map<string, int>::const_iterator i =
  160. tbl_code_classno.find ( code );
  161. if ( i == tbl_code_classno.end() )
  162. {
  163. fthrow(Exception, "no classno found for code <" << code << ">" );
  164. } else {
  165. return i->second;
  166. }
  167. }
  168. int ClassNames::numClasses () const
  169. {
  170. return tbl_classno_code.size();
  171. }
  172. void ClassNames::addClass ( int classno, const std::string & code,
  173. const std::string & text )
  174. {
  175. tbl_classno_code[classno] = code;
  176. tbl_text_code[text] = code;
  177. tbl_code_text[code] = text;
  178. tbl_code_classno[code] = classno;
  179. if ( classno > maxClassNo ) maxClassNo = classno;
  180. }
  181. bool ClassNames::existsClassno ( int classno ) const
  182. {
  183. return (tbl_classno_code.find(classno) != tbl_classno_code.end());
  184. }
  185. // refactor-nice.pl: check this substitution
  186. // old: bool ClassNames::existsClassCode ( const string & classcode ) const
  187. bool ClassNames::existsClassCode ( const std::string & classcode ) const
  188. {
  189. return (tbl_code_classno.find(classcode) != tbl_code_classno.end());
  190. }
  191. bool ClassNames::readFromConfig ( const Config & datasetconf,
  192. // refactor-nice.pl: check this substitution
  193. // old: const string & classselection )
  194. const std::string & classselection )
  195. {
  196. datasetconf.getAllS ( "classnames", tbl_code_text );
  197. if ( tbl_code_text.size() <= 0 ) {
  198. fprintf (stderr, "ClassNames: no classnames specified\n");
  199. return false;
  200. }
  201. // reverse map and lower case
  202. for ( map<string, string>::const_iterator i = tbl_code_text.begin();
  203. i != tbl_code_text.end(); i++ )
  204. tbl_text_code [ i->second ] = i->first;
  205. #if defined DEBUG_ClassNames
  206. cerr << "ClassNames::read: selection = " << classselection << endl;
  207. #endif
  208. std::vector<string> classlist;
  209. StringTools::split ( classselection, ',', classlist );
  210. if ( classlist.size() <= 0 )
  211. {
  212. fprintf (stderr, "FATAL ERROR: wrong format for classselection\n");
  213. exit(-1);
  214. } else if ( classlist[0] == "*" )
  215. {
  216. map<string, bool> forbidden_classes;
  217. for ( size_t k = 1 ; k < classlist.size() ; k++ )
  218. if ( classlist[k].substr(0,1) == "-" )
  219. {
  220. // refactor-nice.pl: check this substitution
  221. // old: string f_class = classlist[k].substr(1);
  222. std::string f_class = classlist[k].substr(1);
  223. #if defined DEBUG_ClassNames
  224. fprintf (stderr, "ClassNames: class %s excluded !\n", f_class.c_str() );
  225. #endif
  226. forbidden_classes[ f_class ] = true;
  227. } else {
  228. fprintf (stderr, "FATAL ERROR: wrong format for classselection: *,-class0,class1,...\n");
  229. exit(-1);
  230. }
  231. int classno_seq = 0;
  232. for ( map<string, string>::const_iterator i = tbl_code_text.begin();
  233. i != tbl_code_text.end();
  234. i++,classno_seq++ )
  235. {
  236. const std::string & classname = i->second;
  237. if ( forbidden_classes.find(classname) != forbidden_classes.end() )
  238. continue;
  239. // refactor-nice.pl: check this substitution
  240. // old: string code = tbl_text_code [ i->second ];
  241. std::string code = tbl_text_code [ i->second ];
  242. int classno;
  243. classno = classno_seq;
  244. tbl_classno_code[classno] = code;
  245. tbl_code_classno[code] = classno;
  246. if ( classno > maxClassNo ) maxClassNo = classno;
  247. #if defined DEBUG_ClassNames
  248. fprintf (stderr, "classno %d class code %s class text %s\n", classno, code.c_str(), classname.c_str() );
  249. #endif
  250. }
  251. } else {
  252. #if defined DEBUG_ClassNames
  253. cerr << "list : " << classlist.size() << endl;
  254. #endif
  255. for ( size_t classno_seq = 0 ; classno_seq < classlist.size() ; classno_seq++ )
  256. {
  257. std::string classname = classlist[classno_seq];
  258. if ( tbl_text_code.find ( classname ) != tbl_text_code.end() )
  259. {
  260. std::string code = tbl_text_code [ classname ];
  261. int classno;
  262. classno = classno_seq;
  263. tbl_classno_code[classno] = code;
  264. tbl_code_classno[code] = classno;
  265. if ( classno > maxClassNo ) maxClassNo = classno;
  266. #if defined DEBUG_ClassNames
  267. fprintf (stderr, "classno %d class code %s class text %s\n", (int)classno, code.c_str(), classname.c_str() );
  268. #endif
  269. } else {
  270. fprintf (stderr, "ClassNames::ClassNames: FATAL ERROR class >%s< not found in data set\n", classname.c_str() );
  271. exit(-1);
  272. }
  273. }
  274. }
  275. /****** after all, try to read color coding *******/
  276. map<string, string> list;
  277. datasetconf.getAllS ( "colors", list );
  278. if ( list.size() > 0 ) {
  279. for ( map<string,string>::const_iterator i = list.begin();
  280. i != list.end();
  281. i++ )
  282. {
  283. std::string value = i->second;
  284. std::string classname = i->first;
  285. int _classno = classno(classname);
  286. vector<string> submatches;
  287. if ( StringTools::regexMatch ( value, "^ *([[:digit:]]+) *: *([[:digit:]]+) *: *([[:digit:]]+) *$", submatches )
  288. && ( submatches.size() == 4 ) )
  289. {
  290. int r = StringTools::convert<int> ( submatches[1] );
  291. int g = StringTools::convert<int> ( submatches[2] );
  292. int b = StringTools::convert<int> ( submatches[3] );
  293. long index = 256*(256*r + g) + b;
  294. tbl_color_classno[index] = _classno;
  295. tbl_classno_color[_classno] = index;
  296. } else {
  297. fprintf (stderr, "LabeledFileList: parse error colors >%s<\n", value.c_str() );
  298. exit(-1);
  299. }
  300. }
  301. }
  302. return true;
  303. }
  304. int ClassNames::getMaxClassno () const
  305. {
  306. return maxClassNo;
  307. }
  308. void ClassNames::getRGBColor ( int classno, int & r, int & g, int & b ) const
  309. {
  310. map<int, long>::const_iterator i = tbl_classno_color.find(classno);
  311. if ( i == tbl_classno_color.end() )
  312. {
  313. fprintf (stderr, "ClassNames: no color setting found for class %d\n", classno );
  314. getchar();
  315. double x = classno / (double)numClasses();
  316. double rd, gd, bd;
  317. ICETools::toColor ( x, rd, gd, bd );
  318. r = (int)(255*rd);
  319. g = (int)(255*gd);
  320. b = (int)(255*bd);
  321. } else {
  322. long color = i->second;
  323. b = color % 256;
  324. color /= 256;
  325. g = color % 256;
  326. color /= 256;
  327. r = color % 256;
  328. }
  329. }
  330. void ClassNames::getClassnoFromColor ( int & classno, int r, int g, int b ) const
  331. {
  332. long color = 256*(256*r+g) + b;
  333. map<long, int>::const_iterator i = tbl_color_classno.find(color);
  334. if ( i == tbl_color_classno.end() )
  335. {
  336. classno = -1;
  337. } else {
  338. classno = i->second;
  339. }
  340. }
  341. void ClassNames::labelToRGB ( const NICE::Image & img, NICE::ColorImage & rgb ) const
  342. {
  343. int red, green, blue;
  344. rgb.resize(img.width(), img.height());
  345. for ( int y = 0 ; y < img.height(); y++ )
  346. for ( int x = 0 ; x < img.width(); x++ )
  347. {
  348. int label = img.getPixel(x,y);
  349. getRGBColor ( label, red, green, blue );
  350. rgb.setPixel(x,y,0,red);
  351. rgb.setPixel(x,y,1,green);
  352. rgb.setPixel(x,y,2,blue);
  353. }
  354. }
  355. int ClassNames::getBackgroundClass () const
  356. {
  357. if ( existsClassCode ("various" ) )
  358. return classno("various");
  359. else if ( existsClassCode ("background" ) )
  360. return classno("background");
  361. else if ( existsClassCode ("clutter" ) )
  362. return classno("clutter");
  363. else
  364. return 0;
  365. }
  366. void ClassNames::restore (istream & is, int format)
  367. {
  368. maxClassNo = -1;
  369. while ( ! is.eof() )
  370. {
  371. std::string mytext;
  372. std::string mycode;
  373. int myclassno;
  374. if ( !(is >> mytext) ) break;
  375. if ( !(is >> mycode) ) break;
  376. if ( !(is >> myclassno) ) break;
  377. tbl_code_text.insert ( pair<string, string> ( mycode, mytext ) );
  378. tbl_text_code.insert ( pair<string, string> ( mytext, mycode ) );
  379. tbl_classno_code.insert ( pair<int, string> ( myclassno, mycode ) );
  380. tbl_code_classno.insert ( pair<string, int> ( mycode, myclassno ) );
  381. if ( myclassno > maxClassNo ) maxClassNo = myclassno;
  382. }
  383. }
  384. void ClassNames::store (ostream & os, int format) const
  385. {
  386. assert ( tbl_classno_code.size() == tbl_code_classno.size() );
  387. for ( map<int, string>::const_iterator i = tbl_classno_code.begin() ;
  388. i != tbl_classno_code.end();
  389. i++ )
  390. {
  391. int myclassno = i->first;
  392. std::string mycode = i->second;
  393. std::string mytext = text(myclassno);
  394. os << mytext << "\t" << mycode << "\t" << myclassno << endl;
  395. }
  396. }
  397. void ClassNames::clear ()
  398. {
  399. tbl_code_text.clear();
  400. tbl_text_code.clear();
  401. tbl_classno_code.clear();
  402. tbl_code_classno.clear();
  403. tbl_color_classno.clear();
  404. tbl_classno_color.clear();
  405. }