zoukankan      html  css  js  c++  java
  • OpenCV 批量resize一个文件夹里的所有图像

    OpenCV玩耍(一)批量resize一个文件夹里的所有图像

    鉴于用caffe做实验的时候,里面牵扯到一个问题是必须将训练集和测试集都转成256*256的图像,而官网给出的代码又不会用,所以我用opencv转了。其实opencv只转一幅图会很简单,关键在于“批量”二字,因此本博客应运而生了。

    本博客详细讲解了如何使用opencv批量处理图像,使某一个文件夹内全部图像都resize成256*256的。如果理解了本次博客内容,则不光可以对图像进行resize操作,还可以用来对图像做其它批处理操作。

    1 先用opencv转一幅图像试试

    这一部分怎么来的太简单了就不多说了,直接翻一下opencv中的cvResize函数声明,需要什么参数就填什么。

    #include "cv.h"
    #include "highgui.h"
    #include "math.h"
    #include <iostream>
    using namespace std;
    
    void main()
    {
        IplImage *src;
        IplImage *dst;
        src=cvLoadImage("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\0101.jpg", 0);//载入源图像
        dst=cvCreateImage(cvSize(256,256),src->depth,src->nChannels);//分配一个256*256的目标图像,resize后的结果将放在这里
        if(src==0)
        {
            printf("打开图片失败!");
            exit(0);
        }
        cvNamedWindow("src",CV_WINDOW_AUTOSIZE);//分配一个用以承载图片的窗口
        cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);//分配一个用以承载图片的窗口
        cvShowImage("src",src);//显示src
        cvShowImage("dst",dst);//显示dst
        cvWaitKey(0);
    
        //此处插入resize
        cvResize(src,dst);
        //此处插入resize
        cvSaveImage("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\result\0101.jpg",dst);//保存dst
        cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);//分配一个用以承载图片的窗口
        cvShowImage("dst",dst);//显示dst
        cvWaitKey(0);
    }
    

    【实验结果】

    src:

    这里写图片描述

    dst:

    这里写图片描述

    2 FindFirstFile函数与FindNextFile函数

    使用这两个函数可以遍历整个图像文件夹。以下例子来自于百度百科,按照自己理解注释了。

    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    void main()
    {
        WIN32_FIND_DATA p; //p是一个用于保存文件信息的结构体
        HANDLE h=FindFirstFile("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\*.jpg",&p); 
    
        /*FindFirstFile的返回值是一个句柄,第二个参数p是采用引用的方式,也就是说当这句话执行完毕后结构体p与文件*.jpg相挂钩了*/
    
        cout<<p.cFileName<<endl;//打印被找到的第一个*.jpg的文件名
        while(FindNextFile(h,&p))//p不断后移,寻找下一个、下下一个*.jpg
        {
            cout<<p.cFileName<<endl;
        }
    }

    这一部分是用来遍历整个文件夹里全部jpg类型的图像的。为了方便观察,每当我们的p与一个新的jpg文件挂钩时,都将文件名打印出来。

    【实验结果】

    3 批量resize一个文件夹里的所有图像
    这一部分结合了以上两部分内容。除此之外还需要一点点C++的string类的知识,知道string类实例化出的对象能够方便地进行字符串的拼接。

    3-1 string类对象的正确用法
    需要注意的一点是如果用string类实例化出一个对象,那么这个对象不是字符串,因此像C中用来将字符串转成整数的函数atoi呀,以及字符串里填上全路径用作文件地址索引呀,都是不能直接用这个对象的。
    以“字符串-整数转换”为例:

    string label;
    atoi(label); //错误用法
    atoi(label.c_str());//正确用法

    同理在这里把string类实例化出的对象用作路径索引时,也是不能直接给一个对象,得给出“对象.c_str()”。

    3-2 路径头+文件名=全路径
    这里要谈到将一个文件夹内所有jpg文件批量处理的核心思想。即以下几步:

    (1)在第2节中的结构体p仅能给出它索引到的jpg文件的文件名,而没有给出它们的路径。
    这些文件名如第2节所述,使用p.cFileName即可获取。

    (2)每一幅图像的路径是相同的,只有文件名不同,鉴于这一点,我们应该自行给出这些图像的路径头——即“全路径-文件名”。
    例如对图像C:UsersLJJDesktop测试图caffe实验 esize000.jpg,其中“0000.jpg”是它的文件名,“C:UsersLJJDesktop测试图caffe实验 esize”就是它的路径头。在写成字符串时,应该对反斜杠进行转义字符处理(即写成\):
    ”C:\Users\LJJ\Desktop\测试图\caffe实验\resize\”

    (3)如前述,string类对象可以方便地进行字符串拼接,如:

    string label1=”one”;
    string label2=”two”;
    string AddLabel=label1+label2; 
    
    /*如果cout<<AddLabel,则输出字符串”onetwo”*/

    因此我们可以方便地完成对路径头和文件名的拼接。其中路径头是我们自己给的,文件名则由p.cFileName获取,随着指针p后移,将会索引该文件夹内全部的jpg文件。

    3-3 批量resize代码清单

    #include "cv.h"
    #include "highgui.h"
    #include "math.h"
    #include <iostream>
    #include <string>
    #include <windows.h>
    using namespace std;
    
    void main()
    {
        IplImage *src;
        IplImage *dst;
        WIN32_FIND_DATA p; //指向一个用于保存文件信息的结构体
        HANDLE h=FindFirstFile("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\*.jpg",&p); //FindFirstFile的返回值是一个句柄,第二个参数p是采用引用的方式,也就是说当这句话执行完毕后p就指向该文件*.jpg
    
        //由于p的成员变量只有文件名,而无文件路径,所以必须加上路径头
        string src_route_head="C:\Users\LJJ\Desktop\测试图\caffe实验\resize\"; //源图像的路径头
        string dst_route_head="C:\Users\LJJ\Desktop\测试图\caffe实验\resize\result\";//目标图像的路径头
        string SourceRoute=src_route_head+p.cFileName; //包含了路径头和文件名的全路径
        string DestRoute=dst_route_head+p.cFileName;
    
        src=cvLoadImage(SourceRoute.c_str(), 0);//载入源图像
        dst=cvCreateImage(cvSize(256,256),src->depth,src->nChannels);//分配一个256*256的目标图像,resize后的结果将放在这里
    
        cvResize(src,dst);
        cvSaveImage(DestRoute.c_str(),dst);//保存dst
    
        //到目前为止,我们就已经完成了对目标文件夹中第一幅图像的resize处理与保存,接下来让该文件夹中其余图像也被处理
    
        while(FindNextFile(h,&p)) //p指针不断后移,寻找下一个、下下一个*.jpg
        {
            SourceRoute=src_route_head+p.cFileName; //route是路径头,imageroute是包含了路径头和文件名的全路径
            src=cvLoadImage(SourceRoute.c_str(), 0);//载入源图像
    
            cvResize(src,dst);
    
            DestRoute=dst_route_head+p.cFileName;
            cvSaveImage(DestRoute.c_str(),dst);//保存dst
        }
    }
  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/yumoye/p/10517132.html
Copyright © 2011-2022 走看看