源码:
#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 <direct.h> #include <io.h> #include "tinyxml.h" //#include "TransformEngine.h" //#include "TransformEngine.cpp 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; } bool createDirectory(const std::string folder) { std::string folder_builder; std::string sub; sub.reserve(folder.size()); for (auto it = folder.begin(); it != folder.end(); ++it) { //cout << *(folder.end()-1) << endl; const char c = *it; sub.push_back(c); if (c == '\' || it == folder.end() - 1) { folder_builder.append(sub); if (0 != ::_access(folder_builder.c_str(), 0)) { // this folder not exist if (0 != ::_mkdir(folder_builder.c_str())) { // create failed return false; } } sub.clear(); } } return true; } /** * 根据每个目标的BoundingBox,剪裁图像,保存为文件 * @param img 图像 * @param NodeVector 目标节点数组 * @param objectName 目标名 */ void CropImage(Mat img, vector<TiXmlElement*> NodeVector, string objectName) { int xmin,ymin,xmax,ymax;//从目标节点中读出的包围盒参数 char fileName[256];//剪裁后的图片和其水平翻转图片的文件名 createDirectory(objectName); //遍历目标数组 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大小 objectName = objectName+"/"+ objectName+ "%06d.jpg"; sprintf(fileName, objectName.c_str(),++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, objectName); } 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:\temp\CropObjectFromVOC\" + XMLName + ".jpg"; XMLName = "D:\temp\CropObjectFromVOC\" + XMLName + ".xml"; src = imread(ImgName); CropImageAccordingToXML(XMLName,src,"person");//根据XML标注文档,从图像src中剪裁出所有person目标,保存为文件 CropImageAccordingToXML(XMLName, src, "chair"); CropImageAccordingToXML(XMLName, src, "tvmonitor"); CropImageAccordingToXML(XMLName, src, "bottle"); } system("pause"); }
test.txt:
2007_000346
2009_000010
2009_000010.xml:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<annotation> <filename>2009_000010.jpg</filename> <folder>VOC2012</folder> <object> <name>tvmonitor</name> <bndbox> <xmax>124</xmax> <xmin>36</xmin> <ymax>241</ymax> <ymin>153</ymin> </bndbox> <difficult>0</difficult> <occluded>1</occluded> <pose>Frontal</pose> <truncated>0</truncated> </object> <object> <name>chair</name> <bndbox> <xmax>164</xmax> <xmin>72</xmin> <ymax>286</ymax> <ymin>205</ymin> </bndbox> <difficult>0</difficult> <occluded>1</occluded> <pose>Unspecified</pose> <truncated>1</truncated> </object> <object> <name>person</name> <bndbox> <xmax>346</xmax> <xmin>157</xmin> <ymax>267</ymax> <ymin>57</ymin> </bndbox> <difficult>0</difficult> <occluded>1</occluded> <pose>Frontal</pose> <truncated>1</truncated> </object> <segmented>0</segmented> <size> <depth>3</depth> <height>375</height> <width>500</width> </size> <source> <annotation>PASCAL VOC2009</annotation> <database>The VOC2009 Database</database> <image>flickr</image> </source> </annotation>
2007_000346.xml:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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>
2007_000346.jpg:
2009_000010.jpg:
免责声明:资源与源码皆来自网络的测试数据,如有侵权请联系本人删除