利用TinyXML读取VOC2012数据集的XML标注文件裁剪出所有人体目标保存为文件

转载自:利用TinyXML读取VOC2012数据集的XML标注文件裁剪出所有人体目标保存为文件 - Why So SerIoUs? - 博客频道 - CSDN.NET http://blog.csdn.net/masibuaa/article/details/16104717

PASCAL VOC目标检测数据集(The PASCAL Visual Object Classes)

http://pascallin.ecs.soton.ac.uk/challenges/VOC/


图片中的目标用XML文件标注,格式为:

[html] view plain copy
  1. <annotation>
  2. folder>VOC2012</>
  3. filename>2007_000346.jpgsourcedatabase>TheVOC2007Database>PASCALVOC2007image>flickrsizewidth>500height>375depth>3segmented>1objectname>bottlepose>Unspecifiedtruncated>0difficultbndBoxxmin>124ymin>107xmax>230ymax>343>person>137>78>497>89>202>129>247>Frontal>72>209>111>259>
对应的图片为:



所以如果想用这个数据集做某种目标识别的训练集的话,需要先从中裁出需要的目标。

下面这个程序就是这个目的,其中用到了TinyXML这个简单易用的XML解析器(XML入门)

[cpp] copy
    #include<iostream>
  1. #include<fstream>
  2. #include<opencv2/core/core.hpp>
  3. #include<opencv2/highgui/highgui.hpp>
  4. #include<opencv2/imgproc/imgproc.hpp>
  5. #include<opencv2/objdetect/objdetect.hpp>
  6. #include<opencv2/ml/ml.hpp>
  7. #include<tinyxml.h>
  8. usingnamespacestd;
  9. namespacecv;
  10. intCropImageCount=0;//裁剪出来的人体图片个数
  11. /**
  12. *通过根节点和节点名查找所有指定节点,结果放到节点数组NodeVector中
  13. *@parampRootElexml文件的根节点
  14. *@paramstrNodeName要查询的节点名
  15. *@paramNodeVector查询到的节点指针数组
  16. *@return找到至少一个相应节点,返回true;否则false
  17. */
  18. boolGetAllNodePointerByName(tixmlElement*pRootEle,stringstrNodeName,vector<tixmlElement*>&NodeVector)
  19. {
  20. //如果NodeName等于根节点名,加入NodeVector数组
  21. if(strNodeName==pRootEle->Value())
  22. {
  23. NodeVector.push_back(pRootEle);//添加到数组末尾
  24. //这里根据VOCAnnotation的XML文件格式,认为相同节点名的节点不会有父子关系,所以所有相同节点名的节点都在同一级别上
  25. //只要找到第一个,剩下的肯定在它的兄弟节点里面
  26. for(tixmlElement*pElement=pRootEle->NextSiblingElement();pElement;pElement=pElement->NextSiblingElement())
  27. if(strNodeName==pElement->Value())
  28. NodeVector.push_back(pElement);
  29. returntrue;
  30. }
  31. tixmlElement*pEle=pRootEle;
  32. for(pEle=pRootEle->FirstChildElement();pEle;pEle=pEle->NextSiblingElement())
  33. //递归处理子节点,获取节点指针
  34. if(GetAllNodePointerByName(pEle,strNodeName,NodeVector))
  35. true;
  36. }
  37. false;//没找到
  38. *根据目标名过滤目标节点数组,删除所有目标名不是objectName的元素
  39. *@paramNodeVector要操作的tixmlElement元素指针数组
  40. *@paramobjectName指定的目标名,删除所有目标名不是objectName的元素
  41. *@return过滤后目标数组为空,返回false;否则返回true
  42. */
  43. boolFiltObject(vector<tixmlElement*>&NodeVector,stringobjectName)
  44. tixmlElement*pEle=NULL;
  45. vector<tixmlElement*>::iteratoriter=NodeVector.begin();//数组的迭代器
  46. for(;iter!=NodeVector.end();)
  47. pEle=*iter;//第i个元素
  48. //若目标名不是objectName,删除此节点
  49. if(objectName!=pEle->FirstChildElement()->GetText())
  50. //cout<<"删除的目标节点:"<<pEle->FirstChildElement()->GetText()<<endl;
  51. iter=NodeVector.erase(iter);//删除目标名不是objectName的,返回下一个元素的指针
  52. else
  53. iter++;
  54. if(0==NodeVector.size())//过滤后目标数组为空,说明不包含指定目标
  55. false;
  56. else
  57. *根据每个目标的BoundingBox,剪裁图像,保存为文件
  58. *@paramimg图像
  59. *@paramNodeVector目标节点数组
  60. voidCropImage(Matimg,vector<tixmlElement*>NodeVector)
  61. intxmin,ymin,xmax,ymax;//从目标节点中读出的包围盒参数
  62. charfileName[256];//剪裁后的图片和其水平翻转图片文件
  63. //遍历目标数组
  64. for(;iter!=NodeVector.end();iter++)
  65. //遍历每个目标的子节点
  66. tixmlElement*pEle=(*iter)->FirstChildElement();//第i个元素的第一个孩子
  67. for(;pEle;pEle=pEle->NextSiblingElement())
  68. //找到包围盒"bndBox"节点
  69. if(string("bndBox")==pEle->Value())
  70. tixmlElement*pCoord=pEle->FirstChildElement();//包围盒的第一个坐标值
  71. //依次遍历包围盒的4个坐标值,放入整型变量中
  72. for(;pCoord;pCoord=pCoord->NextSiblingElement())
  73. if(string("xmin")==pCoord->Value())
  74. xmin=atoi(pCoord->GetText());//xmin
  75. if(string("ymin")==pCoord->Value())
  76. ymin=atoi(pCoord->GetText());//ymin
  77. if(string("xmax")==pCoord->Value())
  78. xmax=atoi(pCoord->GetText());//xmax
  79. if(string("ymax")==pCoord->Value())
  80. ymax=atoi(pCoord->GetText());//ymax
  81. //cout<<"xmin:"<<xmin<<","<<"ymin:"<<ymin<<","<<"xmax:"<<xmax<<","<<"ymax:"<<ymax<<endl;;
  82. //根据读取的包围盒坐标设置图像ROI
  83. MatimgROI=img(Rect(xmin,xmax-xmin,ymax-ymin));
  84. resize(imgROI,imgROI,Size(64,128));//缩放为64*128大小
  85. sprintf(fileName,"person%06d.jpg",++CropImageCount);//生成剪裁图片文件
  86. imwrite(fileName,imgROI);//保存文件
  87. flip(imgROI,1);//水平翻转
  88. memset(fileName,0x00,sizeof(fileName));
  89. //生成剪裁图片的水平翻转图片文件
  90. /**
  91. *根据XML文件,从图像中剪裁出objectName目标
  92. *@paramXMLFileXML文件
  93. *@paramimg对应的图像
  94. *@paramobjectName目标名
  95. *@return若图像中包含objectName目标,返回true;否则返回false
  96. boolCropImageAccordingToXML(stringXMLFile,Matimg,248)"> tixmlDocument*pDoc=newtixmlDocument();//创建XML文档
  97. pDoc->LoadFile(XMLFile.c_str());//装载XML文件
  98. vector<tixmlElement*>nodeVector;//节点数组
  99. //查找所有节点名是object的节点,即目标节点,结果放到节点数组nodeVector中
  100. if(false==GetAllNodePointerByName(pDoc->RootElement(),"object",nodeVector))//未找到指定目标
  101. false;
  102. //cout<<"所有目标个数:"<<nodeVector.size()<<endl;
  103. //过滤节点数组,删除所有节点名不是objectName的节点
  104. false==FiltObject(nodeVector,objectName))//目标数组中没有指定目标
  105. //cout<<"过滤后的目标个数:"<<nodeVector.size()<<endl;
  106. //根据每个目标的BoundingBox,剪裁图像,保存为文件
  107. CropImage(img,nodeVector);
  108. intmain()
  109. intfileCount=0;//文件个数
  110. Matsrc;
  111. stringXMLName,ImgName;//XML文件名和对应的图片文件
  112. //ifstreamfin("VOC2012AnnotationsXMLList.txt");//打开XML文件列表
  113. ifstreamfin("subset.txt");
  114. //ifstreamfin("test.txt");
  115. //读取XML文件列表
  116. while(getline(fin,XMLName))
  117. cout<<"处理:"<<XMLName<<endl;
  118. ImgName="D:\\DataSet\\VOCtrainval_11-May-2012\\VOCdevkit\\VOC2012\\JPEGImages\\"+XMLName+".jpg";
  119. XMLName="D:\\DataSet\\VOCtrainval_11-May-2012\\VOCdevkit\\VOC2012\\Annotations\\"+XMLName+".xml";
  120. src=imread(ImgName);
  121. CropImageAccordingToXML(XMLName,src,"person");//根据XML标注文档,从图像src中剪裁出所有person目标,保存为文件
  122. system("pause");
  123. }

源码下载,环境为VS2010 + OpenCV2.4.4 + TinyXML2.6.2

http://download.csdn.net/detail/masikkk/6547823

编译好的TinyXML2.6.2:

http://download.csdn.net/detail/masikkk/6547809

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念