利用TinyXML讀取VOC2012資料集的XML標註檔案裁剪出所有人體目標儲存為檔案
PASCAL VOC目標檢測資料集(The PASCAL Visual Object Classes)
原始碼下載,環境為VS2010 + OpenCV2.4.4 + TinyXML2.6.2
http://pascallin.ecs.soton.ac.uk/challenges/VOC/
圖片中的目標用XML檔案標註,格式為:
<annotation>
<folder>VOC2012</folder>
<filename>2007_000346.jpg</filename>
<source>
<database>The VOC2007 Database</database>
<annotation>PASCAL VOC2007</annotation>
<image>flickr</image>
</source>
<size>
<width>500</width>
<height>375</height>
<depth>3</depth>
</size>
<segmented>1</segmented>
<object>
<name>bottle</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>124</xmin>
<ymin>107</ymin>
<xmax>230</xmax>
<ymax>343</ymax>
</bndbox>
</object>
<object>
<name>person</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>137</xmin>
<ymin>78</ymin>
<xmax>497</xmax>
<ymax>375</ymax>
</bndbox>
</object>
<object>
<name>person</name>
<pose>Unspecified</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>89</xmin>
<ymin>202</ymin>
<xmax>129</xmax>
<ymax>247</ymax>
</bndbox>
</object>
<object>
<name>person</name>
<pose>Frontal</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>72</xmin>
<ymin>209</ymin>
<xmax>111</xmax>
<ymax>259</ymax>
</bndbox>
</object>
</annotation>
對應的圖片為:
所以如果想用這個資料集做某種目標識別的訓練集的話,需要先從中裁出需要的目標。
下面這個程式就是這個目的,其中用到了TinyXML這個簡單易用的XML解析器(XML入門)
#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/ml/ml.hpp>
#include <tinyxml.h>
using namespace std;
using namespace cv;
int CropImageCount=0;//裁剪出來的人體圖片個數
/**
* 通過根節點和節點名查詢所有指定節點,結果放到節點陣列NodeVector中
* @param pRootEle xml檔案的根節點
* @param strNodeName 要查詢的節點名
* @param NodeVector 查詢到的節點指標陣列
* @return 找到至少一個相應節點,返回true;否則false
*/
bool GetAllNodePointerByName(TiXmlElement* pRootEle, string strNodeName, vector<TiXmlElement*> &NodeVector)
{
//如果NodeName等於根節點名,加入NodeVector陣列
if(strNodeName == pRootEle->Value())
{
NodeVector.push_back(pRootEle);//新增到陣列末尾
//這裡根據VOC Annotation的XML檔案格式,認為相同節點名的節點不會有父子關係,所以所有相同節點名的節點都在同一級別上
//只要找到第一個,剩下的肯定在它的兄弟節點裡面
for(TiXmlElement * pElement = pRootEle->NextSiblingElement(); pElement; pElement = pElement->NextSiblingElement())
if(strNodeName == pElement->Value())
NodeVector.push_back(pElement);
return true;
}
TiXmlElement * pEle = pRootEle;
for(pEle = pRootEle->FirstChildElement(); pEle; pEle = pEle->NextSiblingElement())
{
//遞迴處理子節點,獲取節點指標
if(GetAllNodePointerByName(pEle,strNodeName,NodeVector))
return true;
}
return false;//沒找到
}
/**
* 根據目標名過濾目標節點陣列,刪除所有目標名不是objectName的元素
* @param NodeVector 要操作的TiXmlElement元素指標陣列
* @param objectName 指定的目標名,刪除所有目標名不是objectName的元素
* @return 過濾後目標陣列為空,返回false;否則返回true
*/
bool FiltObject(vector<TiXmlElement*> &NodeVector, string objectName)
{
TiXmlElement * pEle = NULL;
vector<TiXmlElement *>::iterator iter = NodeVector.begin();//陣列的迭代器
for(; iter != NodeVector.end();)
{
pEle = * iter;//第i個元素
//若目標名不是objectName,刪除此節點
if( objectName != pEle->FirstChildElement()->GetText() )
{
//cout<<"刪除的目標節點:"<<pEle->FirstChildElement()->GetText() <<endl;
iter = NodeVector.erase(iter);//刪除目標名不是objectName的,返回下一個元素的指標
}
else
iter++;
}
if( 0 == NodeVector.size())//過濾後目標陣列為空,說明不包含指定目標
return false;
else
return true;
}
/**
* 根據每個目標的BoundingBox,剪裁影象,儲存為檔案
* @param img 影象
* @param NodeVector 目標節點陣列
*/
void CropImage(Mat img, vector<TiXmlElement*> NodeVector)
{
int xmin,ymin,xmax,ymax;//從目標節點中讀出的包圍盒引數
char fileName[256];//剪裁後的圖片和其水平翻轉圖片的檔名
//遍歷目標陣列
vector<TiXmlElement *>::iterator iter = NodeVector.begin();//陣列的迭代器
for(; iter != NodeVector.end(); iter++)
{
//遍歷每個目標的子節點
TiXmlElement *pEle = (*iter)->FirstChildElement();//第i個元素的第一個孩子
for(; pEle; pEle = pEle->NextSiblingElement())
{
//找到包圍盒"bndbox"節點
if(string("bndbox") == pEle->Value())
{
TiXmlElement * pCoord= pEle->FirstChildElement();//包圍盒的第一個座標值
//依次遍歷包圍盒的4個座標值,放入整型變數中
for(; pCoord; pCoord = pCoord->NextSiblingElement())
{
if(string("xmin") == pCoord->Value())
xmin = atoi(pCoord->GetText());//xmin
if(string("ymin") == pCoord->Value())
ymin = atoi(pCoord->GetText());//ymin
if(string("xmax") == pCoord->Value())
xmax = atoi(pCoord->GetText());//xmax
if(string("ymax") == pCoord->Value())
ymax = atoi(pCoord->GetText());//ymax
}
//cout<<"xmin:"<<xmin<<","<<"ymin:"<<ymin<<","<<"xmax:"<<xmax<<","<<"ymax:"<<ymax<<endl;;
//根據讀取的包圍盒座標設定影象ROI
Mat imgROI = img(Rect(xmin,ymin,xmax-xmin,ymax-ymin));
resize(imgROI,imgROI,Size(64,128));//縮放為64*128大小
sprintf(fileName,"person%06d.jpg",++CropImageCount);//生成剪裁圖片的檔名
imwrite(fileName,imgROI);//儲存檔案
flip(imgROI,imgROI,1);//水平翻轉
memset(fileName,0x00,sizeof(fileName));
sprintf(fileName,"person%06d.jpg",++CropImageCount);//生成剪裁圖片的水平翻轉圖片的檔名
imwrite(fileName,imgROI);//儲存檔案
}
}
}
}
/**
* 根據XML檔案,從影象中剪裁出objectName目標
* @param XMLFile XML檔名
* @param img 對應的影象
* @param objectName 目標名
* @return 若影象中包含objectName目標,返回true;否則返回false
*/
bool CropImageAccordingToXML(string XMLFile, Mat img, string objectName)
{
TiXmlDocument * pDoc = new TiXmlDocument();//建立XML文件
pDoc->LoadFile(XMLFile.c_str());//裝載XML檔案
vector<TiXmlElement*> nodeVector;//節點陣列
//查詢所有節點名是object的節點,即目標節點,結果放到節點陣列nodeVector中
if( false == GetAllNodePointerByName(pDoc->RootElement(), "object", nodeVector) )//未找到指定目標
return false;
//cout<<"所有目標個數:"<<nodeVector.size()<<endl;
//過濾節點陣列,刪除所有節點名不是objectName的節點
if( false == FiltObject(nodeVector,objectName) )//目標陣列中沒有指定目標
return false;
//cout<<"過濾後的目標個數:"<<nodeVector.size()<<endl;
//根據每個目標的BoundingBox,剪裁影象,儲存為檔案
CropImage(img,nodeVector);
}
int main()
{
int fileCount=0;//檔案個數
Mat src;
string XMLName,ImgName;//XML檔名和對應的圖片檔名
//ifstream fin("VOC2012AnnotationsXMLList.txt");//開啟XML檔案列表
ifstream fin("subset.txt");
//ifstream fin("test.txt");
//讀取XML檔案列表
while(getline(fin,XMLName))
{
cout<<"處理:"<<XMLName<<endl;
ImgName = "D:\\DataSet\\VOCtrainval_11-May-2012\\VOCdevkit\\VOC2012\\JPEGImages\\" + XMLName + ".jpg";
XMLName = "D:\\DataSet\\VOCtrainval_11-May-2012\\VOCdevkit\\VOC2012\\Annotations\\" + XMLName + ".xml";
src = imread(ImgName);
CropImageAccordingToXML(XMLName,src,"person");//根據XML標註文件,從影象src中剪裁出所有person目標,儲存為檔案
}
system("pause");
}
原始碼下載,環境為VS2010 + OpenCV2.4.4 + TinyXML2.6.2
http://download.csdn.net/detail/masikkk/6547823
編譯好的TinyXML2.6.2:
http://download.csdn.net/detail/masikkk/6547809
利用TinyXML讀取VOC2012資料集的XML標註檔案裁剪出所有人體目標儲存為檔案
相關文章
- 如何用Python讀取xml檔案後,裁剪標註圖片和擴容資料PythonXML
- Pandas之EXCEL資料讀取/儲存/檔案分割/檔案合併Excel
- Python -讀取,儲存檔案Python
- python讀取檔案——python讀取和儲存mat檔案Python
- Java讀取以.xlsx結尾的excel檔案,並寫出每張表對應的c#類、java類、儲存資料的xml檔案、讀取xml檔案的工具類JavaExcelC#XML
- Springboot整合MongoDB儲存檔案、讀取檔案Spring BootMongoDB
- 資料儲存--檔案儲存
- JAVA 讀取xml檔案JavaXML
- Android儲存讀取txt檔案Android
- java mysql儲存和讀取檔案JavaMySql
- 將座標系統儲存為一個檔案.prj
- XMl 檔案屬性的讀取XML
- Java系列:讀取XML檔案JavaXML
- C#讀取Xml檔案C#XML
- 用JDOM讀取XML檔案XML
- (slam工具)1檔案讀取和儲存SLAM
- 讀取xml檔案 解析雙層xmlXML
- java去除xml檔案中的標籤JavaXML
- javaseverlet實現的http標頭檔案的讀取JavaHTTP
- C/C++使用VOID指標儲存結構體資料到二進位制檔案並且讀取C++指標結構體
- SaxReader讀取,更新xml檔案XML
- NSXMLDocument讀取遠端XML檔案XML
- golang 讀取切分儲存byte流檔案Golang
- Python讀取、儲存、檢視.mat檔案Python
- 資料檔案是否是smallfile型別檔案,其儲存是否達到資料檔案儲存上限,是否是多個資料檔案型別
- 目標檢測資料集,全部有標註
- HDFS讀檔案過程分析:讀取檔案的Block資料BloC
- 讀取資料夾檔案
- NFS導致的目標端檔案系統不可讀NFS
- Android中的資料儲存之檔案儲存Android
- 簡單讀取XML檔案中的值XML
- 把檔案系統的資料檔案遷移到ASM儲存ASM
- PHP匯出大量資料,儲存為CSV檔案PHP
- QDomDocument 讀取和編輯xml檔案XML
- Java讀取多層級xml檔案JavaXML
- Matlab將.mat檔案儲存為.txt檔案Matlab
- IOS資料儲存之檔案沙盒儲存iOS
- 【Python標準庫:fileinput】優雅的讀取檔案Python