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

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

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

    1 先用opencv转一幅图像试试

     1 #include "cv.h"
     2 #include "highgui.h"
     3 #include "math.h"
     4 #include <iostream>
     5 using namespace std;
     6 
     7 void main()
     8 {
     9     IplImage *src;
    10     IplImage *dst;
    11     src=cvLoadImage("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\0101.jpg", 0);//载入源图像
    12     dst=cvCreateImage(cvSize(256,256),src->depth,src->nChannels);//分配一个256*256的目标图像,resize后的结果将放在这里
    13     if(src==0)
    14     {
    15         printf("打开图片失败!");
    16         exit(0);
    17     }
    18     cvNamedWindow("src",CV_WINDOW_AUTOSIZE);//分配一个用以承载图片的窗口
    19     cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);//分配一个用以承载图片的窗口
    20     cvShowImage("src",src);//显示src
    21     cvShowImage("dst",dst);//显示dst
    22     cvWaitKey(0);
    23 
    24     //此处插入resize
    25     cvResize(src,dst);
    26     //此处插入resize
    27     cvSaveImage("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\result\0101.jpg",dst);//保存dst
    28     cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);//分配一个用以承载图片的窗口
    29     cvShowImage("dst",dst);//显示dst
    30     cvWaitKey(0);
    31 }

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

    【实验结果】

    src:

     

    dst:

     

    2 FindFirstFile函数与FindNextFile函数

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

     1 #include <iostream>
     2 #include <windows.h>
     3 using namespace std;
     4 
     5 void main()
     6 {
     7     WIN32_FIND_DATA p; //p是一个用于保存文件信息的结构体
     8     HANDLE h=FindFirstFile("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\*.jpg",&p); 
     9 
    10 /*FindFirstFile的返回值是一个句柄,第二个参数p是采用引用的方式,也就是说当这句话执行完毕后p就指向该文件*.jpg*/
    11 
    12     cout<<p.cFileName<<endl;//打印被找到的第一个*.jpg的文件名
    13     while(FindNextFile(h,&p)) //p不断后移,寻找下一个、下下一个*.jpg
    14     {
    15         cout<<p.cFileName<<endl;
    16     }
    17 }

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

    【实验结果】

     

    3 批量resize一个文件夹里的所有图像

    这一部分结合了以上两部分内容。除此之外还需要一点点C++的string类的知识,知道string类实例化出的对象能够方便地进行字符串的拼接。

    3-1 string类对象的正确用法

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

    以“字符串-整数转换”为例:

    1 string label;
    2 
    3 label_int=atoi(label); //错误用法
    4 
    5 label_int=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类对象可以方便地进行字符串拼接,如:

    1 string label1=”one”;
    2 
    3 string label2=”two”;
    4 
    5 string label=label1+label2; //如果cout<<label,则输出字符串”onetwo”

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

    3-3 批量resize代码清单

     1 #include "cv.h"
     2 #include "highgui.h"
     3 #include "math.h"
     4 #include <iostream>
     5 #include <string>
     6 #include <windows.h>
     7 using namespace std;
     8 
     9 void main()
    10 {
    11     IplImage *src;
    12     IplImage *dst;
    13     WIN32_FIND_DATA p; //指向一个用于保存文件信息的结构体
    14     HANDLE h=FindFirstFile("C:\Users\LJJ\Desktop\测试图\caffe实验\resize\*.jpg",&p); //FindFirstFile的返回值是一个句柄,第二个参数p是采用引用的方式,也就是说当这句话执行完毕后p就指向该文件*.jpg
    15 
    16     //由于p的成员变量只有文件名,而无文件路径,所以必须加上路径头
    17     string src_route_head="C:\Users\LJJ\Desktop\测试图\caffe实验\resize\"; //源图像的路径头
    18     string dst_route_head="C:\Users\LJJ\Desktop\测试图\caffe实验\resize\result\";//目标图像的路径头
    19     string SourceRoute=src_route_head+p.cFileName; //包含了路径头和文件名的全路径
    20     string DestRoute=dst_route_head+p.cFileName;
    21 
    22     src=cvLoadImage(SourceRoute.c_str(), 0);//载入源图像
    23     dst=cvCreateImage(cvSize(256,256),src->depth,src->nChannels);//分配一个256*256的目标图像,resize后的结果将放在这里
    24 
    25     cvResize(src,dst);
    26     cvSaveImage(DestRoute.c_str(),dst);//保存dst
    27 
    28     //到目前为止,我们就已经完成了对目标文件夹中第一幅图像的resize处理与保存,接下来让该文件夹中其余图像也被处理
    29 
    30     while(FindNextFile(h,&p)) //p指针不断后移,寻找下一个、下下一个*.jpg
    31     {
    32         SourceRoute=src_route_head+p.cFileName;
    33         src=cvLoadImage(SourceRoute.c_str(), 0);//载入源图像
    34 
    35         cvResize(src,dst);
    36     
    37         DestRoute=dst_route_head+p.cFileName;
    38         cvSaveImage(DestRoute.c_str(),dst);//保存dst
    39     }
    40 }

    2016.5.11

    by 悠望南山

  • 相关阅读:
    JAVA安装
    capture格式布局
    CSS样式表
    进制的转换
    CentOs7设置主机名称,以及主机名称和ip的对应关系
    CentOS7中NAT网卡设置静态IP
    CentOs7安装配置JDK
    基于Go语言构建区块链:part5
    基于Go语言构建区块链:part4
    BoltDB使用笔记
  • 原文地址:https://www.cnblogs.com/NanShan2016/p/5483488.html
Copyright © 2011-2022 走看看