ImageInfo.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. QString string_buffer;
  69. int width = -1;
  70. int height = -1;
  71. // cout << "\nlet the parsing begin!\n";
  72. while(!rootNode.isNull()) {
  73. QDomElement element = rootNode.toElement();
  74. if(!element.isNull()) {
  75. /* path to the image */
  76. if (element.tagName() == "image") {
  77. string_buffer = element.text();
  78. if (string_buffer.isEmpty())
  79. {
  80. cout << "loadImageInfo:The file with data"
  81. " doesn't contain path to the image\n";
  82. return false;
  83. }
  84. if( QFileInfo(string_buffer).isRelative() )
  85. {
  86. QString asd = QFileInfo( QString(aFilename.c_str()) ).absoluteDir().absolutePath();
  87. QString qwe = QFileInfo( asd + "/" + string_buffer ).absoluteFilePath();
  88. string_buffer = qwe;
  89. }
  90. image_path_ = string_buffer.toStdString();
  91. }
  92. /* path to the segmented image */
  93. if (element.tagName() == "segmented") {
  94. string_buffer = element.text();
  95. if ( !string_buffer.isEmpty() ) {
  96. QByteArray array = string_buffer.toAscii();
  97. segmented_image_path_ = string(array.data());
  98. }
  99. }
  100. /* image description */
  101. else if (element.tagName() == "description") {
  102. string_buffer = element.text();
  103. if ( !string_buffer.isEmpty()) {
  104. QByteArray array = string_buffer.toAscii();
  105. image_description_ = string(array.data());
  106. }
  107. }
  108. /* tags */
  109. else if (element.tagName() == "tags") {
  110. string_buffer = element.text();
  111. if ( !string_buffer.isEmpty()) {
  112. QByteArray array = string_buffer.toAscii();
  113. //TODO: make parsing into the string list
  114. tags_ = string(array.data());
  115. }
  116. }
  117. /* legend */
  118. else if (element.tagName() == "legend") {
  119. loadLegendFromElement(&element);
  120. }
  121. /* objects */
  122. else if (element.tagName() == "objects") {
  123. QDomNode subNode = element.firstChild();
  124. QDomElement subElement;
  125. while(!subNode.isNull()) {
  126. subElement = subNode.toElement();
  127. if (subElement.isNull() || subElement.text().isEmpty()) {
  128. subNode = subNode.nextSibling();
  129. continue;
  130. }
  131. string_buffer = subElement.attribute("id");
  132. bool ok = 1;
  133. int id = string_buffer.toInt(&ok, 10);
  134. if (!ok) {
  135. cout << "loadImageInfo: "
  136. "poly id format is corrupted\n";
  137. subNode = subNode.nextSibling();
  138. continue;
  139. }
  140. // try reading a unique object/bounding box id, which identifies
  141. // this object against all others (not a label)
  142. string_buffer = subElement.attribute("uniqueObjectId");
  143. ok = 1;
  144. int uniqueObjectId = string_buffer.toInt(&ok, 10);
  145. if(!ok)
  146. uniqueObjectId = -1;
  147. string_buffer = subElement.text();
  148. if (subElement.tagName() == "bbox") {
  149. BoundingBox bbox;
  150. bool bValid = BBoxFromData(&string_buffer, id, bbox);
  151. if( bValid )
  152. {
  153. bbox.unique_id_ = uniqueObjectId;
  154. bboxes_.push_back(bbox);
  155. }
  156. }
  157. if (subElement.tagName() == "poly") {
  158. Polygon poly;
  159. bool bValid = polyFromData(&string_buffer, poly);
  160. if(bValid)
  161. {
  162. poly.setID(id);
  163. poly.unique_id_ = uniqueObjectId;
  164. polys_.push_back(poly);
  165. }
  166. }
  167. subNode = subNode.nextSibling();
  168. }
  169. }
  170. /* image size */
  171. else if (element.tagName() == "image_size") {
  172. string_buffer = element.text();
  173. if (string_buffer.isEmpty()) {
  174. cout << "loadImageInfo: "
  175. "image size format is corrupted\n";
  176. return false;
  177. /* NOTREACHED */
  178. }
  179. QString buffer;
  180. int size = string_buffer.size();
  181. bool ok = 0;
  182. for (int i = 0; i < size; i++) {
  183. /* ";" is a separator */
  184. if (';' != string_buffer.at(i))
  185. continue;
  186. buffer = string_buffer.mid(0, i);
  187. width = buffer.toInt(&ok, 10);
  188. if (!ok) {
  189. cout <<
  190. "loadImageInfo: "
  191. "image size format is corrupted\n";
  192. return false;
  193. /* NOTREACHED */
  194. }
  195. buffer = string_buffer.mid(i + 1, size - (i + 1));
  196. height = buffer.toInt(&ok, 10);
  197. if (!ok) {
  198. cout <<
  199. "loadImageInfo: "
  200. "image size format is corrupted";
  201. return false;
  202. /* NOTREACHED */
  203. }
  204. break;
  205. }
  206. }
  207. else if (element.tagName() == "pure_data") {
  208. string_buffer = element.text();
  209. labeled_image_ = imageTFromData(width, height, &string_buffer);
  210. }
  211. }
  212. rootNode = rootNode.nextSibling();
  213. }
  214. #endif //NICE_USELIB_QT4_XML
  215. return true;
  216. }
  217. #ifdef NICE_USELIB_QT4_XML
  218. //! A member loading legend from xml node
  219. /*!
  220. * \param[in] anElement a pointer to the object containing all the legend
  221. */
  222. void
  223. ImageInfo::loadLegendFromElement(QDomElement *anElement)
  224. {
  225. if (!anElement) {
  226. return;
  227. /* NOTREACHED */
  228. }
  229. QDomNode subNode = anElement->firstChild();
  230. QDomElement subElement;
  231. while(!subNode.isNull()) {
  232. subElement = subNode.toElement();
  233. if (!subElement.isNull() && !subElement.text().isEmpty())
  234. loadCategoryInfo(&subElement);
  235. subNode = subNode.nextSibling();
  236. }
  237. }
  238. //! Loads one category info(label) from xml QDomElement
  239. /*!
  240. * \param[in] anElement an object containing category info data
  241. */
  242. bool
  243. ImageInfo::loadCategoryInfo(QDomElement *anElement)
  244. {
  245. QString string_buffer;
  246. int id = -1;
  247. bool isMain;
  248. uint color = 0xff000000;
  249. /* id attribute */
  250. string_buffer = anElement->attribute("id");
  251. bool ok = 0;
  252. id = string_buffer.toInt(&ok, 10);
  253. if (!ok) {
  254. cout <<
  255. "loadCategoryInfo: "
  256. "label id format is corrupted\n";
  257. return false;
  258. /* NOTREACHED */
  259. }
  260. /* isMain attribute */
  261. string_buffer = anElement->attribute("isMain");
  262. isMain = string_buffer.toInt(&ok, 2);
  263. if (!ok) {
  264. cout <<
  265. "loadCategoryInfo: "
  266. "label isMain flag format is corrupted\n";
  267. return false;
  268. /* NOTREACHED */
  269. }
  270. /* color attribute */
  271. string_buffer = anElement->attribute("color");
  272. color = string_buffer.toUInt(&ok, 16);
  273. if (!ok) {
  274. cout <<
  275. "loadCategoryInfo: "
  276. "label color format is corrupted\n";
  277. return false;
  278. /* NOTREACHED */
  279. }
  280. /* converting label name from QString to std::string*/
  281. string_buffer = anElement->text();
  282. QByteArray array = string_buffer.toAscii();
  283. std::string labelName(array.data());
  284. CategoryInfo label;
  285. label.setID(id);
  286. label.setCategoryName(labelName);
  287. label.setColor(color);
  288. labels_.push_back(label);
  289. return true;
  290. }
  291. //! A protected member parsing string data and returning a BoundingBox from it
  292. /*!
  293. * format is x;y;w;h where w - width and h - height
  294. */
  295. bool ImageInfo::BBoxFromData( QString *aBBoxData, int &id, BoundingBox &p_bbox )
  296. {
  297. p_bbox.setID(id);
  298. QStringList coordsList = aBBoxData->split(";", QString::SkipEmptyParts);
  299. try
  300. {
  301. if( coordsList.size() == 4)
  302. {
  303. int x = QVariant(coordsList[0]).toInt();
  304. int y = QVariant(coordsList[1]).toInt();
  305. int w = QVariant(coordsList[2]).toInt();
  306. int h = QVariant(coordsList[3]).toInt();
  307. p_bbox.setTopLeft(x,y);
  308. p_bbox.setWidth( w );
  309. p_bbox.setHeight( h );
  310. }
  311. else
  312. {
  313. std::cout <<
  314. "BBoxFromData: "
  315. "bbox format is corrupted\n";
  316. return false;
  317. }
  318. }
  319. catch(std::exception &e)
  320. {
  321. std::cout << "BBoxFromData: exception:" << e.what() << std::endl;
  322. return false;
  323. }
  324. if ( !p_bbox.isValid() )
  325. {
  326. std::cout << "BBoxFromData not valid:"<< aBBoxData->toStdString() << std::endl;
  327. p_bbox.setTopLeft(0, 0);
  328. p_bbox.setBottomRight(0, 0);
  329. return false;
  330. }
  331. return true;
  332. }
  333. //! A protected member parsing string data and returning a Polygon from it
  334. /*!
  335. * format is x0;y0;x1;y1;...
  336. */
  337. bool ImageInfo::polyFromData( QString *aPolyData, Polygon &p_Poly)
  338. {
  339. QStringList coordsList = aPolyData->split(";", QString::SkipEmptyParts);
  340. try
  341. {
  342. if( coordsList.size() % 2 == 0)
  343. {
  344. for( int i = 0; i < coordsList.size(); i += 2)
  345. {
  346. p_Poly.push( QVariant(coordsList[i]).toInt(),
  347. QVariant(coordsList[i+1]).toInt() );
  348. }
  349. }
  350. else
  351. {
  352. std::cout << "polyFromData: not valid (coordinates not multiple of two)" << std::endl;
  353. return false;
  354. }
  355. }
  356. catch(std::exception &e)
  357. {
  358. std::cout << "polyFromData: exception:" << e.what() << std::endl;
  359. return false;
  360. }
  361. return true;
  362. }
  363. //!
  364. ImageT< unsigned int >
  365. ImageInfo::imageTFromData(
  366. const int &aWidth,
  367. const int &aHeight,
  368. QString *aPureData
  369. )
  370. {
  371. int startPos = 0;
  372. QString buffer = 0;
  373. ImageT< unsigned int > image(aWidth, aHeight);
  374. int y = 0;
  375. int x = 0;
  376. bool ok = 0;
  377. for (int i = 0; i < aPureData->size(); i++) {
  378. if ('\n' == aPureData->at(i)) {
  379. y++;
  380. x = 0;
  381. startPos = i + 1;
  382. continue;
  383. }
  384. /* ";" is a separator */
  385. if (';' != aPureData->at(i))
  386. continue;
  387. buffer = aPureData->mid(startPos, i - startPos);
  388. int pixel = buffer.toInt(&ok, 10);
  389. if (!ok) {
  390. cout <<
  391. "imageTFromData: "
  392. "pure data format is corrupted\n";
  393. image = 0;
  394. return image;
  395. /* NOTREACHED */
  396. }
  397. image.setPixel(x, y, pixel);
  398. x++;
  399. startPos = i + 1;
  400. }
  401. return image;
  402. }
  403. #endif //NICE_USELIB_QT4_XML
  404. //! returns pointer to labels_ list
  405. const std::list< CategoryInfo > *
  406. ImageInfo::labels() const
  407. {
  408. return &labels_;
  409. }
  410. //! returns pointer to bboxes_ list
  411. const std::list< BoundingBox > *
  412. ImageInfo::bboxes() const
  413. {
  414. return &bboxes_;
  415. }
  416. //! returns pointer to polys_ list
  417. const std::list< Polygon > *
  418. ImageInfo::polys() const
  419. {
  420. return &polys_;
  421. }
  422. //! returns ImageT object labeled_image_
  423. ImageT< unsigned int >
  424. ImageInfo::labeledImage() const
  425. {
  426. return labeled_image_;
  427. }
  428. //! returns tags
  429. std::string
  430. ImageInfo::tags() const
  431. {
  432. return tags_;
  433. }
  434. //! returns path to the original image
  435. std::string
  436. ImageInfo::imagePath() const
  437. {
  438. return image_path_;
  439. }
  440. //! returns string with the image description
  441. std::string
  442. ImageInfo::imageDescription() const
  443. {
  444. return image_description_;
  445. }
  446. //! returns path to the image segmented by ImageLabeler tool
  447. std::string
  448. ImageInfo::segmentedImagePath() const
  449. {
  450. return segmented_image_path_;
  451. }
  452. /*
  453. *
  454. */