ImageInfo.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /**
  2. * @file ImageInfo.cpp
  3. * @brief localization info + image filename + ?
  4. * @author Erik Rodner
  5. * @date 04/16/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 "vislearning/cbaselib/ImageInfo.h"
  12. /* Qt */
  13. #ifdef NICE_USELIB_QT4_XML
  14. #include <QFile>
  15. #include <QFileInfo>
  16. #include <QDir>
  17. #include <QString>
  18. #include <QByteArray>
  19. #include <QDomDocument>
  20. #include <QDomNode>
  21. #include <QDomElement>
  22. #include <QPoint>
  23. #include <QStringList>
  24. #include <QVariant>
  25. #endif //NICE_USELIB_QT4_XML
  26. using namespace OBJREC;
  27. using namespace std;
  28. using namespace NICE;
  29. ImageInfo::~ImageInfo()
  30. {
  31. //if ( lr != NULL )
  32. //delete lr;
  33. }
  34. //! A member loading labeled image from formatted xml file.
  35. /*!
  36. * \param[in] filename a std::string containing a path to the file
  37. * we need to load data from
  38. *
  39. * \see loadLegendFromNode(QDomElement *)
  40. * \see BBoxFromData(QString *aBBoxData, int *ID)
  41. * \see polyFromData(QString *aPolyData, int *labelID)
  42. */
  43. bool
  44. ImageInfo::loadImageInfo(const string &aFilename)
  45. {
  46. #ifdef NICE_USELIB_QT4_XML
  47. QString filename(aFilename.data());
  48. QDomDocument doc("Image Labeler");
  49. QFile file(filename);
  50. if (!file.open(QIODevice::ReadOnly)) {
  51. cout << "loadImageInfo:Can not open such file\n";
  52. return false;
  53. /* NOTREACHED */
  54. }
  55. QString errMsg;
  56. if (!doc.setContent(&file, &errMsg)) {
  57. QByteArray array = errMsg.toAscii();
  58. cout << array.data();
  59. //showWarning(errMsg);
  60. file.close();
  61. return false;
  62. /* NOTREACHED */
  63. }
  64. file.close();
  65. /* getting all info */
  66. QDomElement elements = doc.documentElement();
  67. QDomNode rootNode = elements.firstChild();
  68. m_iImageWidth = -1;
  69. m_iImageHeight = -1;
  70. // cout << "\nlet the parsing begin!\n";
  71. while(!rootNode.isNull()) {
  72. QDomElement element = rootNode.toElement();
  73. if(!element.isNull()) {
  74. // path to the image
  75. if (element.tagName() == "image") {
  76. if( !this->extractSectionImage( &element, aFilename) )
  77. return false;
  78. }
  79. // path to the segmented image
  80. if (element.tagName() == "segmented") {
  81. if( !this->extractSectionSegmented(&element) )
  82. return false;
  83. }
  84. // image description
  85. else if (element.tagName() == "description") {
  86. if( !this->extractSectionDescription(&element) )
  87. return false;
  88. }
  89. // tags
  90. else if (element.tagName() == "tags") {
  91. if( !this->extractSectionTags(&element) )
  92. return false;
  93. }
  94. // legend
  95. else if (element.tagName() == "legend") {
  96. extractSectionLegend(&element);
  97. }
  98. // objects
  99. else if (element.tagName() == "objects") {
  100. if( !this->extractSectionObjects(&element) )
  101. return false;
  102. }
  103. // image size
  104. else if (element.tagName() == "image_size") {
  105. if( !this->extractImageSize(&element) )
  106. return false;
  107. }
  108. else if (element.tagName() == "pure_data") {
  109. if( !this->extractSectionPureData(&element) )
  110. return false;
  111. }
  112. }
  113. rootNode = rootNode.nextSibling();
  114. }
  115. #endif //NICE_USELIB_QT4_XML
  116. return true;
  117. }
  118. #ifdef NICE_USELIB_QT4_XML
  119. bool ImageInfo::extractSectionImage(QDomElement *element , const std::string &p_sImageInfoFilename)
  120. {
  121. QString string_buffer = element->text();
  122. if (string_buffer.isEmpty())
  123. {
  124. cout << "loadImageInfo:The file with data"
  125. " doesn't contain path to the image\n";
  126. return false;
  127. }
  128. if( QFileInfo(string_buffer).isRelative() )
  129. {
  130. QString asd = QFileInfo( QString(p_sImageInfoFilename.c_str()) ).absoluteDir().absolutePath();
  131. QString qwe = QFileInfo( asd + "/" + string_buffer ).absoluteFilePath();
  132. string_buffer = qwe;
  133. }
  134. image_path_ = string_buffer.toStdString();
  135. return true;
  136. }
  137. bool ImageInfo::extractSectionSegmented(QDomElement *element )
  138. {
  139. QString string_buffer = element->text();
  140. if ( !string_buffer.isEmpty() ) {
  141. QByteArray array = string_buffer.toAscii();
  142. segmented_image_path_ = string(array.data());
  143. }
  144. return true;
  145. }
  146. bool ImageInfo::extractSectionDescription(QDomElement *element )
  147. {
  148. QString string_buffer = element->text();
  149. if ( !string_buffer.isEmpty()) {
  150. QByteArray array = string_buffer.toAscii();
  151. image_description_ = string(array.data());
  152. }
  153. return true;
  154. }
  155. bool ImageInfo::extractSectionTags(QDomElement *element )
  156. {
  157. QString string_buffer = element->text();
  158. if ( !string_buffer.isEmpty())
  159. {
  160. QByteArray array = string_buffer.toAscii();
  161. //TODO: make parsing into the string list
  162. tags_ = string(array.data());
  163. }
  164. return true;
  165. }
  166. bool ImageInfo::extractSectionObjects(QDomElement *element )
  167. {
  168. QDomNode subNode = element->firstChild();
  169. QDomElement subElement;
  170. while(!subNode.isNull()) {
  171. subElement = subNode.toElement();
  172. if (subElement.isNull() || subElement.text().isEmpty()) {
  173. subNode = subNode.nextSibling();
  174. continue;
  175. }
  176. if (subElement.tagName() == "bbox") {
  177. if ( !this->extractObjectRectangle(&subElement) )
  178. return false;
  179. }
  180. if (subElement.tagName() == "poly") {
  181. if ( !this->extractObjectPolygon(&subElement) )
  182. return false;
  183. }
  184. subNode = subNode.nextSibling();
  185. }
  186. return true;
  187. }
  188. bool ImageInfo::extractObjectPolygon(QDomElement *element )
  189. {
  190. QString string_buffer = element->attribute("id");
  191. bool ok = 1;
  192. int id = string_buffer.toInt(&ok, 10);
  193. if (!ok) {
  194. cout << "loadImageInfo: "
  195. "poly id format is corrupted\n";
  196. return false;
  197. }
  198. // try reading a unique object/bounding box id, which identifies
  199. // this object against all others (not a label)
  200. string_buffer = element->attribute("uniqueObjectId");
  201. ok = 1;
  202. int uniqueObjectId = string_buffer.toInt(&ok, 10);
  203. if(!ok)
  204. uniqueObjectId = -1;
  205. string_buffer = element->text();
  206. Polygon poly;
  207. bool bValid = polyFromData(&string_buffer, poly);
  208. if( !bValid )
  209. return false;
  210. poly.setID(id);
  211. poly.unique_id_ = uniqueObjectId;
  212. polys_.push_back(poly);
  213. return true;
  214. }
  215. bool ImageInfo::extractObjectRectangle(QDomElement *element )
  216. {
  217. QString string_buffer = element->attribute("id");
  218. bool ok = 1;
  219. int id = string_buffer.toInt(&ok, 10);
  220. if (!ok)
  221. {
  222. cout << "loadImageInfo: "
  223. "poly id format is corrupted\n";
  224. return false;
  225. }
  226. // try reading a unique object/bounding box id, which identifies
  227. // this object against all others (not a label)
  228. string_buffer = element->attribute("uniqueObjectId");
  229. ok = 1;
  230. int uniqueObjectId = string_buffer.toInt(&ok, 10);
  231. if(!ok)
  232. uniqueObjectId = -1;
  233. string_buffer = element->text();
  234. BoundingBox bbox;
  235. bool bValid = BBoxFromData(&string_buffer, id, bbox);
  236. if( !bValid )
  237. return false;
  238. bbox.unique_id_ = uniqueObjectId;
  239. bboxes_.push_back(bbox);
  240. return true;
  241. }
  242. bool ImageInfo::extractImageSize(QDomElement *element )
  243. {
  244. QString string_buffer = element->text();
  245. if (string_buffer.isEmpty()) {
  246. cout << "loadImageInfo: "
  247. "image size format is corrupted\n";
  248. return false;
  249. }
  250. QStringList coordsList = string_buffer.split(";", QString::SkipEmptyParts);
  251. try
  252. {
  253. if( coordsList.size() == 2)
  254. {
  255. bool ok = false;
  256. this->m_iImageWidth = QVariant(coordsList[0]).toInt( &ok );
  257. if( !ok ) return false;
  258. this->m_iImageHeight = QVariant(coordsList[1]).toInt( &ok );
  259. if( !ok ) return false;
  260. return true;
  261. }
  262. } catch(std::exception &e)
  263. {
  264. std::cout << "exception: image size format is corrupted" << e.what() << std::endl;
  265. return false;
  266. }
  267. return false;
  268. }
  269. bool ImageInfo::extractSectionPureData(QDomElement *element )
  270. {
  271. if( m_iImageHeight < 0 || m_iImageWidth < 0)
  272. return false;
  273. QString string_buffer = element->text();
  274. labeled_image_ = imageTFromData(m_iImageWidth, m_iImageHeight, &string_buffer);
  275. return true;
  276. }
  277. //! A member loading legend from xml node
  278. /*!
  279. * \param[in] anElement a pointer to the object containing all the legend
  280. */
  281. void
  282. ImageInfo::extractSectionLegend(QDomElement *anElement)
  283. {
  284. if (!anElement) {
  285. return;
  286. }
  287. QDomNode subNode = anElement->firstChild();
  288. QDomElement subElement;
  289. while(!subNode.isNull()) {
  290. subElement = subNode.toElement();
  291. if (!subElement.isNull() && !subElement.text().isEmpty())
  292. loadCategoryInfo(&subElement);
  293. subNode = subNode.nextSibling();
  294. }
  295. }
  296. //! Loads one category info(label) from xml QDomElement
  297. /*!
  298. * \param[in] anElement an object containing category info data
  299. */
  300. bool
  301. ImageInfo::loadCategoryInfo(QDomElement *anElement)
  302. {
  303. QString string_buffer;
  304. int id = -1;
  305. bool isMain;
  306. uint color = 0xff000000;
  307. /* id attribute */
  308. string_buffer = anElement->attribute("id");
  309. bool ok = 0;
  310. id = string_buffer.toInt(&ok, 10);
  311. if (!ok) {
  312. cout <<
  313. "loadCategoryInfo: "
  314. "label id format is corrupted\n";
  315. return false;
  316. /* NOTREACHED */
  317. }
  318. /* isMain attribute */
  319. string_buffer = anElement->attribute("isMain");
  320. isMain = string_buffer.toInt(&ok, 2);
  321. if (!ok) {
  322. cout <<
  323. "loadCategoryInfo: "
  324. "label isMain flag format is corrupted\n";
  325. return false;
  326. /* NOTREACHED */
  327. }
  328. /* color attribute */
  329. string_buffer = anElement->attribute("color");
  330. color = string_buffer.toUInt(&ok, 16);
  331. if (!ok) {
  332. cout <<
  333. "loadCategoryInfo: "
  334. "label color format is corrupted\n";
  335. return false;
  336. /* NOTREACHED */
  337. }
  338. /* converting label name from QString to std::string*/
  339. string_buffer = anElement->text();
  340. QByteArray array = string_buffer.toAscii();
  341. std::string labelName(array.data());
  342. CategoryInfo label;
  343. label.setID(id);
  344. label.setCategoryName(labelName);
  345. label.setColor(color);
  346. labels_.push_back(label);
  347. return true;
  348. }
  349. //! A protected member parsing string data and returning a BoundingBox from it
  350. /*!
  351. * format is x;y;w;h where w - width and h - height
  352. */
  353. bool ImageInfo::BBoxFromData( QString *aBBoxData, int &id, BoundingBox &p_bbox )
  354. {
  355. p_bbox.setID(id);
  356. QStringList coordsList = aBBoxData->split(";", QString::SkipEmptyParts);
  357. try
  358. {
  359. if( coordsList.size() == 4)
  360. {
  361. int x = QVariant(coordsList[0]).toInt();
  362. int y = QVariant(coordsList[1]).toInt();
  363. int w = QVariant(coordsList[2]).toInt();
  364. int h = QVariant(coordsList[3]).toInt();
  365. p_bbox.setTopLeft(x,y);
  366. p_bbox.setWidth( w );
  367. p_bbox.setHeight( h );
  368. }
  369. else
  370. {
  371. std::cout <<
  372. "BBoxFromData: "
  373. "bbox format is corrupted\n";
  374. return false;
  375. }
  376. }
  377. catch(std::exception &e)
  378. {
  379. std::cout << "BBoxFromData: exception:" << e.what() << std::endl;
  380. return false;
  381. }
  382. if ( !p_bbox.isValid() )
  383. {
  384. std::cout << "BBoxFromData not valid:"<< aBBoxData->toStdString() << std::endl;
  385. p_bbox.setTopLeft(0, 0);
  386. p_bbox.setBottomRight(0, 0);
  387. return false;
  388. }
  389. return true;
  390. }
  391. //! A protected member parsing string data and returning a Polygon from it
  392. /*!
  393. * format is x0;y0;x1;y1;...
  394. */
  395. bool ImageInfo::polyFromData( QString *aPolyData, Polygon &p_Poly)
  396. {
  397. QStringList coordsList = aPolyData->split(";", QString::SkipEmptyParts);
  398. try
  399. {
  400. if( coordsList.size() % 2 == 0)
  401. {
  402. for( int i = 0; i < coordsList.size(); i += 2)
  403. {
  404. p_Poly.push( QVariant(coordsList[i]).toInt(),
  405. QVariant(coordsList[i+1]).toInt() );
  406. }
  407. }
  408. else
  409. {
  410. std::cout << "polyFromData: not valid (coordinates not multiple of two)" << std::endl;
  411. return false;
  412. }
  413. }
  414. catch(std::exception &e)
  415. {
  416. std::cout << "polyFromData: exception:" << e.what() << std::endl;
  417. return false;
  418. }
  419. return true;
  420. }
  421. //!
  422. ImageT< unsigned int >
  423. ImageInfo::imageTFromData(
  424. const int &aWidth,
  425. const int &aHeight,
  426. QString *aPureData
  427. )
  428. {
  429. int startPos = 0;
  430. QString buffer = 0;
  431. ImageT< unsigned int > image(aWidth, aHeight);
  432. int y = 0;
  433. int x = 0;
  434. bool ok = 0;
  435. for (int i = 0; i < aPureData->size(); i++) {
  436. if ('\n' == aPureData->at(i)) {
  437. y++;
  438. x = 0;
  439. startPos = i + 1;
  440. continue;
  441. }
  442. /* ";" is a separator */
  443. if (';' != aPureData->at(i))
  444. continue;
  445. buffer = aPureData->mid(startPos, i - startPos);
  446. int pixel = buffer.toInt(&ok, 10);
  447. if (!ok) {
  448. cout <<
  449. "imageTFromData: "
  450. "pure data format is corrupted\n";
  451. image = 0;
  452. return image;
  453. /* NOTREACHED */
  454. }
  455. image.setPixel(x, y, pixel);
  456. x++;
  457. startPos = i + 1;
  458. }
  459. return image;
  460. }
  461. #endif //NICE_USELIB_QT4_XML
  462. //! returns pointer to labels_ list
  463. const std::list< CategoryInfo > *
  464. ImageInfo::labels() const
  465. {
  466. return &labels_;
  467. }
  468. //! returns pointer to bboxes_ list
  469. const std::list< BoundingBox > *
  470. ImageInfo::bboxes() const
  471. {
  472. return &bboxes_;
  473. }
  474. //! returns pointer to polys_ list
  475. const std::list< Polygon > *
  476. ImageInfo::polys() const
  477. {
  478. return &polys_;
  479. }
  480. //! returns ImageT object labeled_image_
  481. ImageT< unsigned int >
  482. ImageInfo::labeledImage() const
  483. {
  484. return labeled_image_;
  485. }
  486. //! returns tags
  487. std::string
  488. ImageInfo::tags() const
  489. {
  490. return tags_;
  491. }
  492. //! returns path to the original image
  493. std::string
  494. ImageInfo::imagePath() const
  495. {
  496. return image_path_;
  497. }
  498. //! returns string with the image description
  499. std::string
  500. ImageInfo::imageDescription() const
  501. {
  502. return image_description_;
  503. }
  504. //! returns path to the image segmented by ImageLabeler tool
  505. std::string
  506. ImageInfo::segmentedImagePath() const
  507. {
  508. return segmented_image_path_;
  509. }
  510. /*
  511. *
  512. */