• [原][源码][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:

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

  • 相关阅读:
    熊逸吴军武志红万维钢薛兆丰等得到专栏书34本,5星1本,4星12本
    2星|罗大伦《道德经说什么》:比熊逸《道可道》李零《人往低处走》差很多
    樊登力荐的《道德经说什么》,比熊逸《道可道》差两颗星
    Mysql授权允许远程访问解决Navicat for MySQL连接mysql提示客户端不支持服务器请求的身份验证协议;考虑升级MySQL客户端
    使用Vue-cli 脚手架生成的项目使用Vetur+ Prettier + ESlint的配置设置代码规范和格式
    URL中的hash(井号)
    Redis集群的部署
    Redis用作分布式锁
    Redis 概述安装
    简单的Asp.net core管道模拟
  • 原文地址:https://www.cnblogs.com/lyggqm/p/9394381.html
Copyright © 2020-2023  润新知