一、按照我的上篇博客(点击打开链接)配置好环境;
二、根据PASCAL VOC的xml文件的格式构建基类“Annotation”。
1、PASCAL VOC的xml文件的格式如下:
<annotation> <folder>VOC2007</folder> <filename>000001.jpg</filename> <source> <database>The VOC2007 Database</database> <annotation>PASCAL VOC2007</annotation> <image>flickr</image> <flickrid>341012865</flickrid> </source> <owner> <flickrid>Fried Camels</flickrid> <name>Jinky the Fruit Bat</name> </owner> <size> <width>353</width> <height>500</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>dog</name> <pose>Left</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>48</xmin> <ymin>240</ymin> <xmax>195</xmax> <ymax>371</ymax> </bndbox> </object> <object> <name>person</name> <pose>Left</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>8</xmin> <ymin>12</ymin> <xmax>352</xmax> <ymax>498</ymax> </bndbox> </object> </annotation>
#include <stdio.h> #include <string> #include <iostream> #include <vector> using namespace std; typedef struct _Source { string database; string annotation; string image; string flickrid; } Source, *PSource; typedef struct _Owner { string flickrid; string name; } Owner, *POwner; typedef struct _Size { int width; int height; int depth; } Size, *PSize; typedef struct _RECT { int xmin; int ymin; int xmax; int ymax; } RECT, *PRECT; typedef struct _Object { string name; string pose; string truncated; string difficult; RECT bndbox; } Object, *PObject; class Annotation { public: string folder; string filename; Source source; Owner owner; Size size; string segmented; vector<Object> objectList; Object object; Annotation(); virtual ~Annotation(); };
三、xml文件读取:
void XMLRead(const char* xmlPath, Annotation & annotation){ xmlDocPtr doc; xmlNodePtr curNode; xmlChar *szKey; string filename = ""; doc = xmlReadFile(xmlPath, "UTF-8", XML_PARSE_RECOVER); //解析文件"GB2312" if (doc == NULL){ fprintf(stderr, "Document not parsed successfully.\n"); } curNode = xmlDocGetRootElement(doc); //确定文档根元素 if (NULL == curNode){ fprintf(stderr, "empty document\n"); xmlFreeDoc(doc); } if (xmlStrcmp(curNode->name, BAD_CAST "annotation")) { fprintf(stderr, "document of the wrong type, root node != Message"); xmlFreeDoc(doc); } curNode = curNode->xmlChildrenNode; xmlNodePtr propNodePtr = curNode; xmlNodePtr sourceNodePtr = NULL; xmlNodePtr ownerNodePtr = NULL; xmlNodePtr sizeNodePtr = NULL; xmlNodePtr objectNodePtr = NULL; vector<xmlNodePtr> objectListP; xmlNodePtr objectNodePtr2 = NULL; xmlNodePtr bndboxNodePtr = NULL; // annotation while (curNode != NULL){ //取出文件名称 if (!xmlStrcmp(curNode->name, BAD_CAST "folder")) { annotation.folder = (char*)xmlNodeGetContent(curNode); } if (!xmlStrcmp(curNode->name, BAD_CAST "filename")) { annotation.filename = (char*)xmlNodeGetContent(curNode); } if (!xmlStrcmp(curNode->name, BAD_CAST "source")) { sourceNodePtr = curNode->xmlChildrenNode; } if (!xmlStrcmp(curNode->name, BAD_CAST "owner")) { ownerNodePtr = curNode->xmlChildrenNode; } if (!xmlStrcmp(curNode->name, BAD_CAST "size")) { sizeNodePtr = curNode->xmlChildrenNode; } if (!xmlStrcmp(curNode->name, BAD_CAST "segmented")) { annotation.segmented = (char*)xmlNodeGetContent(curNode); } if (!xmlStrcmp(curNode->name, BAD_CAST "object")) { objectNodePtr = curNode->xmlChildrenNode; objectListP.push_back(objectNodePtr); } curNode = curNode->next; } // source while (sourceNodePtr != NULL){ if (!xmlStrcmp(sourceNodePtr->name, BAD_CAST "database")) { annotation.source.database = (char*)xmlNodeGetContent(sourceNodePtr); } if (!xmlStrcmp(sourceNodePtr->name, BAD_CAST "annotation")) { annotation.source.annotation = (char*)xmlNodeGetContent(sourceNodePtr); } if (!xmlStrcmp(sourceNodePtr->name, BAD_CAST "image")) { annotation.source.image = (char*)xmlNodeGetContent(sourceNodePtr); } if (!xmlStrcmp(sourceNodePtr->name, BAD_CAST "flickrid")) { annotation.source.flickrid = (char*)xmlNodeGetContent(sourceNodePtr); } sourceNodePtr = sourceNodePtr->next; } // owner while (ownerNodePtr != NULL){ if (!xmlStrcmp(ownerNodePtr->name, BAD_CAST "flickrid")) { annotation.owner.flickrid = (char*)xmlNodeGetContent(ownerNodePtr); } if (!xmlStrcmp(ownerNodePtr->name, BAD_CAST "name")) { annotation.owner.name = (char*)xmlNodeGetContent(ownerNodePtr); } ownerNodePtr = ownerNodePtr->next; } // size while (sizeNodePtr != NULL){ if (!xmlStrcmp(sizeNodePtr->name, BAD_CAST "width")) { annotation.size.width = atoi((char*)xmlNodeGetContent(sizeNodePtr)); } if (!xmlStrcmp(sizeNodePtr->name, BAD_CAST "height")) { annotation.size.height = atoi((char*)xmlNodeGetContent(sizeNodePtr)); } if (!xmlStrcmp(sizeNodePtr->name, BAD_CAST "depth")) { annotation.size.depth = atoi((char*)xmlNodeGetContent(sizeNodePtr)); } sizeNodePtr = sizeNodePtr->next; } // object for (int i = 0; i < objectListP.size(); i++){ objectNodePtr = objectListP[i]; while (objectNodePtr != NULL) { if (!xmlStrcmp(objectNodePtr->name, BAD_CAST "name")) { annotation.object.name = (char*)xmlNodeGetContent(objectNodePtr); } if (!xmlStrcmp(objectNodePtr->name, BAD_CAST "pose")) { annotation.object.pose = (char*)xmlNodeGetContent(objectNodePtr); } if (!xmlStrcmp(objectNodePtr->name, BAD_CAST "truncated")) { annotation.object.truncated = (char*)xmlNodeGetContent(objectNodePtr); } if (!xmlStrcmp(objectNodePtr->name, BAD_CAST "difficult")) { annotation.object.difficult = (char*)xmlNodeGetContent(objectNodePtr); } if (!xmlStrcmp(objectNodePtr->name, BAD_CAST "bndbox")) { bndboxNodePtr = objectNodePtr->xmlChildrenNode; } objectNodePtr = objectNodePtr->next; } // bndbox while (bndboxNodePtr != NULL){ if (!xmlStrcmp(bndboxNodePtr->name, BAD_CAST "xmin")) { annotation.object.bndbox.xmin = atoi((char*)xmlNodeGetContent(bndboxNodePtr)); } if (!xmlStrcmp(bndboxNodePtr->name, BAD_CAST "ymin")) { annotation.object.bndbox.ymin = atoi((char*)xmlNodeGetContent(bndboxNodePtr)); } if (!xmlStrcmp(bndboxNodePtr->name, BAD_CAST "xmax")) { annotation.object.bndbox.xmax = atoi((char*)xmlNodeGetContent(bndboxNodePtr)); } if (!xmlStrcmp(bndboxNodePtr->name, BAD_CAST "ymax")) { annotation.object.bndbox.ymax = atoi((char*)xmlNodeGetContent(bndboxNodePtr)); } bndboxNodePtr = bndboxNodePtr->next; } annotation.objectList.push_back(annotation.object); } xmlFreeDoc(doc); }
void XMLWrite(const char* xmlPath, Annotation & annotation){ xmlDocPtr doc = NULL; xmlNodePtr root_node = NULL, node = NULL, objectNode = NULL, node1 = NULL; //Creates a new document, a node and set it as a root node doc = xmlNewDoc(BAD_CAST "1.0"); root_node = xmlNewNode(NULL, BAD_CAST "annotation"); //xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "1.0"); xmlDocSetRootElement(doc, root_node); //creates a new node, which is "attached" as child node of root_node node. xmlNewChild(root_node, NULL, BAD_CAST "folder", BAD_CAST annotation.folder.c_str()); xmlNewChild(root_node, NULL, BAD_CAST "filename", BAD_CAST annotation.filename.c_str()); node = xmlNewChild(root_node, NULL, BAD_CAST "source", NULL); xmlNewChild(node, NULL, BAD_CAST "database", BAD_CAST annotation.source.database.c_str()); xmlNewChild(node, NULL, BAD_CAST "annotation", BAD_CAST annotation.source.annotation.c_str()); xmlNewChild(node, NULL, BAD_CAST "image", BAD_CAST annotation.source.image.c_str()); xmlNewChild(node, NULL, BAD_CAST "flickrid", BAD_CAST annotation.source.flickrid.c_str()); node = xmlNewChild(root_node, NULL, BAD_CAST "owner", NULL); xmlNewChild(node, NULL, BAD_CAST "flickrid", BAD_CAST annotation.owner.flickrid.c_str()); xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST annotation.owner.name.c_str()); node = xmlNewChild(root_node, NULL, BAD_CAST "size", NULL); char temp[32]; _itoa(annotation.size.width, temp, 10); xmlNewChild(node, NULL, BAD_CAST "width", BAD_CAST _itoa(annotation.size.width, temp, 10)); xmlNewChild(node, NULL, BAD_CAST "height", BAD_CAST _itoa(annotation.size.height, temp, 10)); xmlNewChild(node, NULL, BAD_CAST "depth", BAD_CAST _itoa(annotation.size.depth, temp, 10)); xmlNewChild(root_node, NULL, BAD_CAST "segmented", BAD_CAST annotation.segmented.c_str()); for (int i = 0; i < annotation.objectList.size(); i++){ objectNode = xmlNewChild(root_node, NULL, BAD_CAST "object", NULL); xmlNewChild(objectNode, NULL, BAD_CAST "name", BAD_CAST annotation.objectList[i].name.c_str()); xmlNewChild(objectNode, NULL, BAD_CAST "pose", BAD_CAST annotation.objectList[i].pose.c_str()); xmlNewChild(objectNode, NULL, BAD_CAST "truncated", BAD_CAST annotation.objectList[i].truncated.c_str()); xmlNewChild(objectNode, NULL, BAD_CAST "difficult", BAD_CAST annotation.objectList[i].difficult.c_str()); node = xmlNewChild(objectNode, NULL, BAD_CAST "bndbox", NULL); xmlNewChild(node, NULL, BAD_CAST "xmin", BAD_CAST _itoa(annotation.objectList[i].bndbox.xmin, temp, 10)); xmlNewChild(node, NULL, BAD_CAST "ymin", BAD_CAST _itoa(annotation.objectList[i].bndbox.ymin, temp, 10)); xmlNewChild(node, NULL, BAD_CAST "xmax", BAD_CAST _itoa(annotation.objectList[i].bndbox.xmax, temp, 10)); xmlNewChild(node, NULL, BAD_CAST "ymax", BAD_CAST _itoa(annotation.objectList[i].bndbox.ymax, temp, 10)); } //// xmlNewProp() creates attributes, which is "attached" to an node. //node = xmlNewChild(root_node, NULL, BAD_CAST "node3", BAD_CAST"node has attributes"); //xmlNewProp(node, BAD_CAST "attribute", BAD_CAST "yes"); ////Here goes another way to create nodes. //node = xmlNewNode(NULL, BAD_CAST "node4"); //node1 = xmlNewText(BAD_CAST"other way to create content"); //xmlAddChild(node, node1); //xmlAddChild(root_node, node); xmlSaveFormatFileEnc(xmlPath, doc, "UTF-8", 1);//Dumping document to stdio or file xmlFreeDoc(doc); xmlCleanupParser(); xmlMemoryDump();//debug memory for regression tests }
五、对PASCAL VOC图像描述的xml文件进行解析,然后重新生成。
int main(){ const char* xmlPath = "C:\\Users\\zyy\\Desktop\\XML_test\\PASCAL\\000001.xml"; //const char* xmlPath = "C:\\Users\\zyy\\Desktop\\XML_test\\ImageNet\\n01440764_18.xml"; Annotation annotation; XMLRead(xmlPath, annotation); XMLWrite("./temp.xml", annotation); //system("pause"); return 0; }
<?xml version="1.0" encoding="UTF-8"?> <annotation> <folder>VOC2007</folder> <filename>000001.jpg</filename> <source> <database>The VOC2007 Database</database> <annotation>PASCAL VOC2007</annotation> <image>flickr</image> <flickrid>341012865</flickrid> </source> <owner> <flickrid>Fried Camels</flickrid> <name>Jinky the Fruit Bat</name> </owner> <size> <width>353</width> <height>500</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>dog</name> <pose>Left</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>48</xmin> <ymin>240</ymin> <xmax>195</xmax> <ymax>371</ymax> </bndbox> </object> <object> <name>person</name> <pose>Left</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>8</xmin> <ymin>12</ymin> <xmax>352</xmax> <ymax>498</ymax> </bndbox> </object> </annotation>