利用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>VOC2012folder>  
  3.     <filename>2007_000346.jpgfilename>  
  4.     <source>  
  5.         <database>The VOC2007 Databasedatabase>  
  6.         <annotation>PASCAL VOC2007annotation>  
  7.         <image>flickrimage>  
  8.     source>  
  9.     <size>  
  10.         <width>500width>  
  11.         <height>375height>  
  12.         <depth>3depth>  
  13.     size>  
  14.     <segmented>1segmented>  
  15.     <object>  
  16.         <name>bottlename>  
  17.         <pose>Unspecifiedpose>  
  18.         <truncated>0truncated>  
  19.         <difficult>0difficult>  
  20.         <bndbox>  
  21.             <xmin>124xmin>  
  22.             <ymin>107ymin>  
  23.             <xmax>230xmax>  
  24.             <ymax>343ymax>  
  25.         bndbox>  
  26.     object>  
  27.     <object>  
  28.         <name>personname>  
  29.         <pose>Unspecifiedpose>  
  30.         <truncated>0truncated>  
  31.         <difficult>0difficult>  
  32.         <bndbox>  
  33.             <xmin>137xmin>  
  34.             <ymin>78ymin>  
  35.             <xmax>497xmax>  
  36.             <ymax>375ymax>  
  37.         bndbox>  
  38.     object>  
  39.     <object>  
  40.         <name>personname>  
  41.         <pose>Unspecifiedpose>  
  42.         <truncated>1truncated>  
  43.         <difficult>0difficult>  
  44.         <bndbox>  
  45.             <xmin>89xmin>  
  46.             <ymin>202ymin>  
  47.             <xmax>129xmax>  
  48.             <ymax>247ymax>  
  49.         bndbox>  
  50.     object>  
  51.     <object>  
  52.         <name>personname>  
  53.         <pose>Frontalpose>  
  54.         <truncated>1truncated>  
  55.         <difficult>0difficult>  
  56.         <bndbox>  
  57.             <xmin>72xmin>  
  58.             <ymin>209ymin>  
  59.             <xmax>111xmax>  
  60.             <ymax>259ymax>  
  61.         bndbox>  
  62.     object>  
  63. annotation>  
对应的图片为:

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

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

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

[cpp]  view plain  copy
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #include   
  8.   
  9. #include   
  10.   
  11. using namespace std;  
  12. using namespace cv;  
  13.   
  14. int CropImageCount=0;//裁剪出来的人体图片个数  
  15.   
  16. /** 
  17. * 通过根节点和节点名查找所有指定节点,结果放到节点数组NodeVector中 
  18. * @param pRootEle xml文件的根节点 
  19. * @param strNodeName 要查询的节点名 
  20. * @param NodeVector 查询到的节点指针数组 
  21. * @return 找到至少一个相应节点,返回true;否则false 
  22. */  
  23. bool GetAllNodePointerByName(TiXmlElement* pRootEle, string strNodeName, vector &NodeVector)  
  24. {  
  25.     //如果NodeName等于根节点名,加入NodeVector数组  
  26.     if(strNodeName == pRootEle->Value())  
  27.     {  
  28.         NodeVector.push_back(pRootEle);//添加到数组末尾  
  29.         //这里根据VOC Annotation的XML文件格式,认为相同节点名的节点不会有父子关系,所以所有相同节点名的节点都在同一级别上  
  30.         //只要找到第一个,剩下的肯定在它的兄弟节点里面  
  31.         for(TiXmlElement * pElement = pRootEle->NextSiblingElement(); pElement; pElement = pElement->NextSiblingElement())  
  32.             if(strNodeName == pElement->Value())  
  33.                 NodeVector.push_back(pElement);  
  34.         return true;  
  35.     }  
  36.     TiXmlElement * pEle = pRootEle;  
  37.     for(pEle = pRootEle->FirstChildElement(); pEle; pEle = pEle->NextSiblingElement())  
  38.     {  
  39.         //递归处理子节点,获取节点指针  
  40.         if(GetAllNodePointerByName(pEle,strNodeName,NodeVector))  
  41.             return true;  
  42.     }  
  43.     return false;//没找到  
  44. }  
  45.   
  46. /** 
  47. * 根据目标名过滤目标节点数组,删除所有目标名不是objectName的元素 
  48. * @param NodeVector 要操作的TiXmlElement元素指针数组 
  49. * @param objectName 指定的目标名,删除所有目标名不是objectName的元素 
  50. * @return 过滤后目标数组为空,返回false;否则返回true 
  51. */  
  52. bool FiltObject(vector &NodeVector, string objectName)  
  53. {  
  54.     TiXmlElement * pEle = NULL;  
  55.     vector::iterator iter = NodeVector.begin();//数组的迭代器  
  56.     for(; iter != NodeVector.end();)  
  57.     {  
  58.         pEle = * iter;//第i个元素  
  59.         //若目标名不是objectName,删除此节点  
  60.         if( objectName != pEle->FirstChildElement()->GetText() )  
  61.         {  
  62.             //cout<<"删除的目标节点:"<FirstChildElement()->GetText() <  
  63.             iter = NodeVector.erase(iter);//删除目标名不是objectName的,返回下一个元素的指针  
  64.         }  
  65.         else  
  66.             iter++;  
  67.     }  
  68.     if( 0 == NodeVector.size())//过滤后目标数组为空,说明不包含指定目标  
  69.         return false;  
  70.     else   
  71.         return true;  
  72. }  
  73.   
  74. /** 
  75. * 根据每个目标的BoundingBox,剪裁图像,保存为文件 
  76. * @param img 图像 
  77. * @param NodeVector 目标节点数组 
  78. */  
  79. void CropImage(Mat img, vector NodeVector)  
  80. {  
  81.     int xmin,ymin,xmax,ymax;//从目标节点中读出的包围盒参数  
  82.     char fileName[256];//剪裁后的图片和其水平翻转图片的文件名  
  83.   
  84.     //遍历目标数组  
  85.     vector::iterator iter = NodeVector.begin();//数组的迭代器  
  86.     for(; iter != NodeVector.end(); iter++)  
  87.     {  
  88.         //遍历每个目标的子节点  
  89.         TiXmlElement *pEle = (*iter)->FirstChildElement();//第i个元素的第一个孩子  
  90.         for(; pEle; pEle = pEle->NextSiblingElement())  
  91.         {  
  92.             //找到包围盒"bndbox"节点  
  93.             if(string("bndbox") == pEle->Value())  
  94.             {  
  95.                 TiXmlElement * pCoord= pEle->FirstChildElement();//包围盒的第一个坐标值  
  96.                 //依次遍历包围盒的4个坐标值,放入整型变量中  
  97.                 for(; pCoord; pCoord = pCoord->NextSiblingElement())  
  98.                 {  
  99.                     if(string("xmin") == pCoord->Value())  
  100.                         xmin = atoi(pCoord->GetText());//xmin  
  101.                     if(string("ymin") == pCoord->Value())  
  102.                         ymin = atoi(pCoord->GetText());//ymin  
  103.                     if(string("xmax") == pCoord->Value())  
  104.                         xmax = atoi(pCoord->GetText());//xmax  
  105.                     if(string("ymax") == pCoord->Value())  
  106.                         ymax = atoi(pCoord->GetText());//ymax  
  107.                 }  
  108.                 //cout<<"xmin:"<  
  109.                 //根据读取的包围盒坐标设置图像ROI  
  110.                 Mat imgROI = img(Rect(xmin,ymin,xmax-xmin,ymax-ymin));  
  111.                 resize(imgROI,imgROI,Size(64,128));//缩放为64*128大小  
  112.                 sprintf(fileName,"person%06d.jpg",++CropImageCount);//生成剪裁图片的文件名  
  113.                 imwrite(fileName,imgROI);//保存文件  
  114.                 flip(imgROI,imgROI,1);//水平翻转  
  115.                 memset(fileName,0x00,sizeof(fileName));  
  116.                 sprintf(fileName,"person%06d.jpg",++CropImageCount);//生成剪裁图片的水平翻转图片的文件名  
  117.                 imwrite(fileName,imgROI);//保存文件  
  118.             }  
  119.         }  
  120.     }  
  121. }  
  122.   
  123. /** 
  124. * 根据XML文件,从图像中剪裁出objectName目标 
  125. * @param XMLFile XML文件名 
  126. * @param img 对应的图像 
  127. * @param objectName 目标名 
  128. * @return 若图像中包含objectName目标,返回true;否则返回false 
  129. */  
  130. bool CropImageAccordingToXML(string XMLFile, Mat img, string objectName)  
  131. {  
  132.     TiXmlDocument * pDoc = new TiXmlDocument();//创建XML文档  
  133.     pDoc->LoadFile(XMLFile.c_str());//装载XML文件  
  134.     vector nodeVector;//节点数组  
  135.   
  136.     //查找所有节点名是object的节点,即目标节点,结果放到节点数组nodeVector中  
  137.     iffalse == GetAllNodePointerByName(pDoc->RootElement(), "object", nodeVector) )//未找到指定目标  
  138.         return false;  
  139.     //cout<<"所有目标个数:"<  
  140.   
  141.     //过滤节点数组,删除所有节点名不是objectName的节点  
  142.     iffalse == FiltObject(nodeVector,objectName) )//目标数组中没有指定目标  
  143.         return false;  
  144.     //cout<<"过滤后的目标个数:"<  
  145.   
  146.     //根据每个目标的BoundingBox,剪裁图像,保存为文件  
  147.     CropImage(img,nodeVector);  
  148. }  
  149.   
  150.   
  151. int main()  
  152. {  
  153.     int fileCount=0;//文件个数  
  154.     Mat src;  
  155.     string XMLName,ImgName;//XML文件名和对应的图片文件名  
  156.     //ifstream fin("VOC2012AnnotationsXMLList.txt");//打开XML文件列表  
  157.     ifstream fin("subset.txt");  
  158.     //ifstream fin("test.txt");  
  159.   
  160.     //读取XML文件列表  
  161.     while(getline(fin,XMLName))  
  162.     {  
  163.         cout<<"处理:"<
  164.         ImgName = "D:\\DataSet\\VOCtrainval_11-May-2012\\VOCdevkit\\VOC2012\\JPEGImages\\" + XMLName + ".jpg";  
  165.         XMLName = "D:\\DataSet\\VOCtrainval_11-May-2012\\VOCdevkit\\VOC2012\\Annotations\\" + XMLName + ".xml";  
  166.         src = imread(ImgName);  
  167.         CropImageAccordingToXML(XMLName,src,"person");//根据XML标注文档,从图像src中剪裁出所有person目标,保存为文件  
  168.     }  
  169.   
  170.     system("pause");  
  171. }  

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

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

编译好的TinyXML2.6.2:

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


你可能感兴趣的:(目标检测(Object,Detection))