/** * @file ImageInfo.cpp * @brief localization info + image filename + ? * @author Erik Rodner * @date 04/16/2008 */ #include "core/image/ImageT.h" #include "core/vector/VectorT.h" #include "core/vector/MatrixT.h" #include #include "vislearning/cbaselib/ImageInfo.h" /* Qt */ #ifdef NICE_USELIB_QT4_XML #include #include #include #include #include #include #include #include #include #include #include #endif //NICE_USELIB_QT4_XML using namespace OBJREC; using namespace std; using namespace NICE; ImageInfo::~ImageInfo() { //if ( lr != NULL ) //delete lr; } //! A member loading labeled image from formatted xml file. /*! * \param[in] filename a std::string containing a path to the file * we need to load data from * * \see loadLegendFromNode(QDomElement *) * \see BBoxFromData(QString *aBBoxData, int *ID) * \see polyFromData(QString *aPolyData, int *labelID) */ bool ImageInfo::loadImageInfo(const string &aFilename) { #ifdef NICE_USELIB_QT4_XML QString filename(aFilename.data()); QDomDocument doc("Image Labeler"); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { cout << "loadImageInfo:Can not open such file\n"; return false; /* NOTREACHED */ } QString errMsg; if (!doc.setContent(&file, &errMsg)) { QByteArray array = errMsg.toAscii(); cout << array.data(); //showWarning(errMsg); file.close(); return false; /* NOTREACHED */ } file.close(); /* getting all info */ QDomElement elements = doc.documentElement(); QDomNode rootNode = elements.firstChild(); m_iImageWidth = -1; m_iImageHeight = -1; // cout << "\nlet the parsing begin!\n"; while(!rootNode.isNull()) { QDomElement element = rootNode.toElement(); if(!element.isNull()) { // path to the image if (element.tagName() == "image") { if( !this->extractSectionImage( &element, aFilename) ) return false; } // path to the segmented image if (element.tagName() == "segmented") { if( !this->extractSectionSegmented(&element) ) return false; } // image description else if (element.tagName() == "description") { if( !this->extractSectionDescription(&element) ) return false; } // tags else if (element.tagName() == "tags") { if( !this->extractSectionTags(&element) ) return false; } // legend else if (element.tagName() == "legend") { extractSectionLegend(&element); } // objects else if (element.tagName() == "objects") { if( !this->extractSectionObjects(&element) ) return false; } // image size else if (element.tagName() == "image_size") { if( !this->extractImageSize(&element) ) return false; } else if (element.tagName() == "pure_data") { if( !this->extractSectionPureData(&element) ) return false; } } rootNode = rootNode.nextSibling(); } #endif //NICE_USELIB_QT4_XML return true; } #ifdef NICE_USELIB_QT4_XML bool ImageInfo::extractSectionImage(QDomElement *element , const std::string &p_sImageInfoFilename) { QString string_buffer = element->text(); if (string_buffer.isEmpty()) { cout << "loadImageInfo:The file with data" " doesn't contain path to the image\n"; return false; } if( QFileInfo(string_buffer).isRelative() ) { QString asd = QFileInfo( QString(p_sImageInfoFilename.c_str()) ).absoluteDir().absolutePath(); QString qwe = QFileInfo( asd + "/" + string_buffer ).absoluteFilePath(); string_buffer = qwe; } image_path_ = string_buffer.toStdString(); return true; } bool ImageInfo::extractSectionSegmented(QDomElement *element ) { QString string_buffer = element->text(); if ( !string_buffer.isEmpty() ) { QByteArray array = string_buffer.toAscii(); segmented_image_path_ = string(array.data()); } return true; } bool ImageInfo::extractSectionDescription(QDomElement *element ) { QString string_buffer = element->text(); if ( !string_buffer.isEmpty()) { QByteArray array = string_buffer.toAscii(); image_description_ = string(array.data()); } return true; } bool ImageInfo::extractSectionTags(QDomElement *element ) { QString string_buffer = element->text(); if ( !string_buffer.isEmpty()) { QByteArray array = string_buffer.toAscii(); //TODO: make parsing into the string list tags_ = string(array.data()); } return true; } bool ImageInfo::extractSectionObjects(QDomElement *element ) { QDomNode subNode = element->firstChild(); QDomElement subElement; while(!subNode.isNull()) { subElement = subNode.toElement(); if (subElement.isNull() || subElement.text().isEmpty()) { subNode = subNode.nextSibling(); continue; } if (subElement.tagName() == "bbox") { if ( !this->extractObjectRectangle(&subElement) ) return false; } if (subElement.tagName() == "poly") { if ( !this->extractObjectPolygon(&subElement) ) return false; } subNode = subNode.nextSibling(); } return true; } bool ImageInfo::extractObjectPolygon(QDomElement *element ) { QString string_buffer = element->attribute("id"); bool ok = 1; int id = string_buffer.toInt(&ok, 10); if (!ok) { cout << "loadImageInfo: " "poly id format is corrupted\n"; return false; } // try reading a unique object/bounding box id, which identifies // this object against all others (not a label) string_buffer = element->attribute("uniqueObjectId"); ok = 1; int uniqueObjectId = string_buffer.toInt(&ok, 10); if(!ok) uniqueObjectId = -1; string_buffer = element->text(); Polygon poly; bool bValid = polyFromData(&string_buffer, poly); if( !bValid ) return false; poly.setID(id); poly.unique_id_ = uniqueObjectId; polys_.push_back(poly); return true; } bool ImageInfo::extractObjectRectangle(QDomElement *element ) { QString string_buffer = element->attribute("id"); bool ok = 1; int id = string_buffer.toInt(&ok, 10); if (!ok) { cout << "loadImageInfo: " "poly id format is corrupted\n"; return false; } // try reading a unique object/bounding box id, which identifies // this object against all others (not a label) string_buffer = element->attribute("uniqueObjectId"); ok = 1; int uniqueObjectId = string_buffer.toInt(&ok, 10); if(!ok) uniqueObjectId = -1; string_buffer = element->text(); BoundingBox bbox; bool bValid = BBoxFromData(&string_buffer, id, bbox); if( !bValid ) return false; bbox.unique_id_ = uniqueObjectId; bboxes_.push_back(bbox); return true; } bool ImageInfo::extractImageSize(QDomElement *element ) { QString string_buffer = element->text(); if (string_buffer.isEmpty()) { cout << "loadImageInfo: " "image size format is corrupted\n"; return false; } QStringList coordsList = string_buffer.split(";", QString::SkipEmptyParts); try { if( coordsList.size() == 2) { bool ok = false; this->m_iImageWidth = QVariant(coordsList[0]).toInt( &ok ); if( !ok ) return false; this->m_iImageHeight = QVariant(coordsList[1]).toInt( &ok ); if( !ok ) return false; return true; } } catch(std::exception &e) { std::cout << "exception: image size format is corrupted" << e.what() << std::endl; return false; } return false; } bool ImageInfo::extractSectionPureData(QDomElement *element ) { if( m_iImageHeight < 0 || m_iImageWidth < 0) return false; QString string_buffer = element->text(); labeled_image_ = imageTFromData(m_iImageWidth, m_iImageHeight, &string_buffer); return true; } //! A member loading legend from xml node /*! * \param[in] anElement a pointer to the object containing all the legend */ void ImageInfo::extractSectionLegend(QDomElement *anElement) { if (!anElement) { return; } QDomNode subNode = anElement->firstChild(); QDomElement subElement; while(!subNode.isNull()) { subElement = subNode.toElement(); if (!subElement.isNull() && !subElement.text().isEmpty()) loadCategoryInfo(&subElement); subNode = subNode.nextSibling(); } } //! Loads one category info(label) from xml QDomElement /*! * \param[in] anElement an object containing category info data */ bool ImageInfo::loadCategoryInfo(QDomElement *anElement) { QString string_buffer; int id = -1; bool isMain; uint color = 0xff000000; /* id attribute */ string_buffer = anElement->attribute("id"); bool ok = 0; id = string_buffer.toInt(&ok, 10); if (!ok) { cout << "loadCategoryInfo: " "label id format is corrupted\n"; return false; /* NOTREACHED */ } /* isMain attribute */ string_buffer = anElement->attribute("isMain"); isMain = string_buffer.toInt(&ok, 2); if (!ok) { cout << "loadCategoryInfo: " "label isMain flag format is corrupted\n"; return false; /* NOTREACHED */ } /* color attribute */ string_buffer = anElement->attribute("color"); color = string_buffer.toUInt(&ok, 16); if (!ok) { cout << "loadCategoryInfo: " "label color format is corrupted\n"; return false; /* NOTREACHED */ } /* converting label name from QString to std::string*/ string_buffer = anElement->text(); QByteArray array = string_buffer.toAscii(); std::string labelName(array.data()); CategoryInfo label; label.setID(id); label.setCategoryName(labelName); label.setColor(color); labels_.push_back(label); return true; } //! A protected member parsing string data and returning a BoundingBox from it /*! * format is x;y;w;h where w - width and h - height */ bool ImageInfo::BBoxFromData( QString *aBBoxData, int &id, BoundingBox &p_bbox ) { p_bbox.setID(id); QStringList coordsList = aBBoxData->split(";", QString::SkipEmptyParts); try { if( coordsList.size() == 4) { int x = QVariant(coordsList[0]).toInt(); int y = QVariant(coordsList[1]).toInt(); int w = QVariant(coordsList[2]).toInt(); int h = QVariant(coordsList[3]).toInt(); p_bbox.setTopLeft(x,y); p_bbox.setWidth( w ); p_bbox.setHeight( h ); } else { std::cout << "BBoxFromData: " "bbox format is corrupted\n"; return false; } } catch(std::exception &e) { std::cout << "BBoxFromData: exception:" << e.what() << std::endl; return false; } if ( !p_bbox.isValid() ) { std::cout << "BBoxFromData not valid:"<< aBBoxData->toStdString() << std::endl; p_bbox.setTopLeft(0, 0); p_bbox.setBottomRight(0, 0); return false; } return true; } //! A protected member parsing string data and returning a Polygon from it /*! * format is x0;y0;x1;y1;... */ bool ImageInfo::polyFromData( QString *aPolyData, Polygon &p_Poly) { QStringList coordsList = aPolyData->split(";", QString::SkipEmptyParts); try { if( coordsList.size() % 2 == 0) { for( int i = 0; i < coordsList.size(); i += 2) { p_Poly.push( QVariant(coordsList[i]).toInt(), QVariant(coordsList[i+1]).toInt() ); } } else { std::cout << "polyFromData: not valid (coordinates not multiple of two)" << std::endl; return false; } } catch(std::exception &e) { std::cout << "polyFromData: exception:" << e.what() << std::endl; return false; } return true; } //! ImageT< unsigned int > ImageInfo::imageTFromData( const int &aWidth, const int &aHeight, QString *aPureData ) { int startPos = 0; QString buffer = 0; ImageT< unsigned int > image(aWidth, aHeight); int y = 0; int x = 0; bool ok = 0; for (int i = 0; i < aPureData->size(); i++) { if ('\n' == aPureData->at(i)) { y++; x = 0; startPos = i + 1; continue; } /* ";" is a separator */ if (';' != aPureData->at(i)) continue; buffer = aPureData->mid(startPos, i - startPos); int pixel = buffer.toInt(&ok, 10); if (!ok) { cout << "imageTFromData: " "pure data format is corrupted\n"; image = 0; return image; /* NOTREACHED */ } image.setPixel(x, y, pixel); x++; startPos = i + 1; } return image; } #endif //NICE_USELIB_QT4_XML //! returns pointer to labels_ list const std::list< CategoryInfo > * ImageInfo::labels() const { return &labels_; } //! returns pointer to bboxes_ list const std::list< BoundingBox > * ImageInfo::bboxes() const { return &bboxes_; } //! returns pointer to polys_ list const std::list< Polygon > * ImageInfo::polys() const { return &polys_; } //! returns ImageT object labeled_image_ ImageT< unsigned int > ImageInfo::labeledImage() const { return labeled_image_; } //! returns tags std::string ImageInfo::tags() const { return tags_; } //! returns path to the original image std::string ImageInfo::imagePath() const { return image_path_; } //! returns string with the image description std::string ImageInfo::imageDescription() const { return image_description_; } //! returns path to the image segmented by ImageLabeler tool std::string ImageInfo::segmentedImagePath() const { return segmented_image_path_; } /* * */