[原][源码][tinyxml][opencv]按照规格剪切所有的图片

源码:

#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:

<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>
View Code

2007_000346.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>
View Code

2007_000346.jpg:

2009_000010.jpg:

免责声明:资源与源码皆来自网络的测试数据,如有侵权请联系本人删除

原文地址:https://www.cnblogs.com/lyggqm/p/9394381.html