欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

caffe学习系列一——图像预处理

程序员文章站 2022-05-10 09:16:49
...

1.批量读取文件夹内文件:(windows下)

1)读取某给定路径下所有文件夹与文件名称,并带完整路径,写入txt文件。代码如下:

 1 void getAllFiles(string path, vector<string>& files) {
 2     //文件句柄
 3     long hFile = 0;
 4     //文件信息
 5     struct _finddata_t fileinfo;  //很少用的文件信息读取结构
 6     string p;  //string类很有意思的一个赋值函数:assign(),有很多重载版本
 7     if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1) {
 8         do {
 9             if ((fileinfo.attrib & _A_SUBDIR)) {  //比较文件类型是否是文件夹
10                 if (strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0) {
11                     files.push_back(p.assign(path).append("\\").append(fileinfo.name));
12                     getAllFiles(p.assign(path).append("\\").append(fileinfo.name), files);
13                 }
14             } else {
15                 files.push_back(p.assign(path).append("\\").append(fileinfo.name));
16             }
17         } while (_findnext(hFile, &fileinfo) == 0);  //寻找下一个,成功返回0,否则-1
18         _findclose(hFile);
19     }
20 }

2)只读取某给定路径下的当前文件夹名(以下类似,只给出函数,调用案例同上):

1 void getJustCurrentDir(string path, vector<string>& files) {
 2     //文件句柄
 3     long hFile = 0;
 4     //文件信息 
 5     struct _finddata_t fileinfo;
 6     string p;
 7     if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1) {
 8         do {  
 9             if ((fileinfo.attrib & _A_SUBDIR)) {  
10                 if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) {
11                     files.push_back(fileinfo.name);
12                     //files.push_back(p.assign(path).append("\\").append(fileinfo.name));
13                 }
14             }
15         } while (_findnext(hFile, &fileinfo) == 0);
16         _findclose(hFile);
17     }
18 }

3)只读取某给定路径下的当前文件名:

 1 void getJustCurrentFile(string path, vector<string>& files) {
 2     //文件句柄
 3     long hFile = 0;
 4     //文件信息
 5     struct _finddata_t fileinfo;
 6     string p;
 7     if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) {
 8         do {
 9             if ((fileinfo.attrib & _A_SUBDIR)) {
10                 ;
11             } else {
12                 files.push_back(fileinfo.name);
13                 //files.push_back(p.assign(path).append("\\").append(fileinfo.name));
14             }
15         } while (_findnext(hFile, &fileinfo) == 0);
16         _findclose(hFile);
17     }
18 }

4)只读取某给定路径下的所有文件名(即包含当前目录及子目录的文件):

1 void getFilesAll(string path, vector<string>& files) {
 2     //文件句柄
 3     long hFile = 0;
 4     //文件信息
 5     struct _finddata_t fileinfo;
 6     string p;  
 7     if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) {
 8         do {
 9             if ((fileinfo.attrib & _A_SUBDIR)) {
10                 if (strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0) {
11                     //files.push_back(p.assign(path).append("\\").append(fileinfo.name));
12                     getFilesAll(p.assign(path).append("\\").append(fileinfo.name), files);
13                 }
14             } else {  
15                 files.push_back(p.assign(path).append("\\").append(fileinfo.name));
16             }
17         } while (_findnext(hFile, &fileinfo) == 0);
18         _findclose(hFile);
19     }
20 }

5)提取文件夹下特定类型的文件:

void GetAllFormatFiles( string path, vector<string>& files,string format)    
{    
    //文件句柄    
    long   hFile   =   0;    
    //文件信息    
    struct _finddata_t fileinfo;    
    string p;    
    if((hFile = _findfirst(p.assign(path).append("\\*" + format).c_str(),&fileinfo)) !=  -1)    
    {    
        do    
        {      
            if((fileinfo.attrib &  _A_SUBDIR))    
            {    
                if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)    
                {  
                    //files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
                    GetAllFormatFiles( p.assign(path).append("\\").append(fileinfo.name), files,format);   
                }  
            }    
            else    
            {    
                files.push_back(p.assign(path).append("\\").append(fileinfo.name) );    
            }    
        }while(_findnext(hFile, &fileinfo)  == 0);    

        _findclose(hFile);   
    }   
}   

参考调用主函数:

#include <io.h>  
#include <fstream>  
#include <string>  
#include <vector>  
#include <iostream>  
 using namespace std; 
  int main()
{
    string filePath = "E:\\program-file\\vs_project\\face_pro\\dlib_test\\dlib_test\\crop0";
    vector<string> files;
    char * distAll = "AllFiles.txt";

    //读取所有的文件,包括子文件的文件
    //GetAllFiles(filePath, files);

    //读取所有格式为jpg的文件
    string format = ".png";
    GetAllFormatFiles(filePath, files, format);
    ofstream ofn(distAll);
    int size = files.size();
    ofn << size << endl;
    for (int i = 0; i<size; i++)
    {
        ofn << files[i] << endl;
        cout << files[i] << endl;
    }

    ofn.close();
    return 0;
}

6)按行读取txt文件并存入数组

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
int main(int args, char **argv)
{
std::ifstream fin("split.txt", std::ios::in);//定义读取的文本文件
char line[1024]={0};//定义读取的每行内容的变量
std::string x = "";
std::string y = "";
std::string z = "";
while(fin.getline(line, sizeof(line)))
{
std::stringstream word(line);//stringstream按空格切分每行内容
word >> x;
word >> y;
word >> z;
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
std::cout << "z: " << z << std::endl;
}
fin.clear();//刷新缓存并关闭文件
fin.close();
return 0;
}

2. dir批量访问文件(windows下):

1)bat文件生成文件名列表

第一步,在要提取文件名的目录下新建一个txt格式的记事本文件;
第二步,在记事本文件中输入:DIR *.*  /B >LIST.TXT;
第三步,将此记事本文件后辍名,由txt改为bat。会弹出重命名对话框,单击“是”;
第四步,双击文件“新建文本文档.bat”即可生成list.txt文件。打开txt文件就可以看到当前文件夹内的所有文件名列表。
(温馨提示:你也可以把文件“新建文本文档.bat”放在其他文件夹里运行,获取当前文件夹下面的所有文件名哦!)

2)DOS下批量访问文件名:

步骤:CMD 进入dos,然后进入cd 命令进入文件夹,输入这个命令 dir /s /b > 1.txt 
**命令详解**:dir 列出文件表  
            /s 是指列出当前目录包含子目录下的所有文件。
            /b 是仅列出文件名称,而日期、大小等信息不列出;如果不加这个,则是显示所有信息。
            >1.txt 将列出的文件名保存到1.txt。   
              注:>符也可以用>>符代替,
              如果“文件名.txt”文件不存在,则>>是创建一个新文件,是没有区别的;   
              如果“文件名.txt”文件已存在,则>是往文件里追加内容,>>是覆盖原有内容

总结:本文的提取文件夹内文件名的方法,思路就是将文件保存到要提取文件名的目录下,保存为.bat(为文件名),然后双击执行就OK了。这也是传送说中的批处理命令还可以对dir命令进行扩展,以过滤和筛选文件。

3.借助bash文件生成文件名清单并标签(linux)

bash文件示例代码:(将cat.jpg和bike.jpg分类并标签,保存为train.txt)

# /usr/bin/env sh
DATA=examples/images
echo "Create train.txt..."
rm -rf $DATA/train.txt
find $DATA -name *cat.jpg | cut -d '/' -f3 | sed "s/$/ 1/">>$DATA/train.txt
find $DATA -name *bike.jpg | cut -d '/' -f3 | sed "s/$/ 2/">>$DATA/tmp.txt
cat $DATA/tmp.txt>>$DATA/train.txt
rm -rf $DATA/tmp.txt
echo "Done.."

代码解释:用到了rm,find, cut, sed,cat等linux命令。
rm: 删除文件
find: 寻找文件
cut: 截取路径
sed: 在每行的最后面加上标注。本例中将找到的*cat.jpg文件加入标注为1,找到的*bike.jpg文件加入标注为2
cat: 将两个类别合并在一个文件里。
注:重定向符号>与>>,前者表示新建重定向文件或者截断,后者表示向文件中接着添加或注入内容;
类比上面代码,生成相应的val.txt和test.txt文件,可以作为caffe自带的convert_imageset.cpp文件第三个参数,进而生成caffe支持的db文件:
convert_imageset.cpp的使用:

convert_imageset [FLAGS] ROOTFOLDER/ LISTFILE DB_NAME

需要带四个参数:

FLAGS: 图片参数组,后面详细介绍

ROOTFOLDER/: 图片存放的绝对路径,从linux系统根目录开始

LISTFILE: 图片文件列表清单,一般为一个txt文件,一行一张图片

DB_NAME: 最终生成的db文件存放目录

如果图片已经下载到本地电脑上了,那么我们首先需要创建一个图片列表清单,保存为txt;

其中FLAGS参数介绍

-gray: 是否以灰度图的方式打开图片。程序调用opencv库中的imread()函数来打开图片,默认为false

-shuffle: 是否随机打乱图片顺序。默认为false

-backend:需要转换成的db文件格式,可选为leveldb或lmdb,默认为lmdb

-resize_width/resize_height: 改变图片的大小。在运行中,要求所有图片的尺寸一致,因此需要改变图片大小。 程序调用opencv库的resize()函数来对图片放大缩小,默认为0,不改变

-check_size: 检查所有的数据是否有相同的尺寸。默认为false,不检查

-encoded: 是否将原图片编码放入最终的数据中,默认为false

-encode_type: 与前一个参数对应,将图片编码为哪一个格式:‘png’,’jpg’……

好了,知道这些参数后,我们就可以调用命令来生成最终的lmdb格式数据了

由于参数比较多,因此我们可以编写一个sh脚本来执行命令:vim create_lmdb.sh

#!/usr/bin/en sh
DATA=examples/images
rm -rf $DATA/img_train_lmdb
build/tools/convert_imageset --shuffle \
--resize_height=256 --resize_width=256 \
/home/xxx/caffe/examples/images/ $DATA/train.txt  $DATA/img_train_lmdb

注释:设置参数-shuffle,打乱图片顺序。
设置参数-resize_height和-resize_width将所有图片尺寸都变为256*256.
/home/xxx/caffe/examples/images/ 为图片保存的绝对路径
运行脚本文件,就会在examples/images/ 目录下生成一个名为 img_train_lmdb的文件夹,里面的文件就是我们需要的db文件了。

4.caffe.proto文件自带的文件与处理功能

1)levelDB,LMDB,hdf5绝大部分数据层在设置时,都可以先对数据进行一定的预处理,包括归一化scale,去中心化(减去平均值),水平镜像flip,随机裁剪crop等四种预处理方式。
该四种预处理方式可以靠该Layer的transform_params属性(HDF5 Layer没有该属性。。。)来指定。指定方式如下:

transform_param {
  # randomly horizontally mirror the image
  mirror: 1
  # crop a `crop_size` x `crop_size` patch:
  # - at random during training
  # - from the center during testing
  crop_size: 227
  # substract mean value(RGB three channel): these mean_values can equivalently be replaced with a mean.binaryproto file as
  # mean_file: name_of_mean_file.binaryproto
  mean_value: 104
  mean_value: 117
  mean_value: 123
}

(2)caffe关于数据不同读取方式下的数据层设置:caffe.proto
数据类型levelDB和lmdb,从数据库读取数据,数据层设置:
数据类型hdf5(支持向量形式):
图片格式文件,数据层设置,参见如下连接:
http://blog.csdn.net/u012177034/article/details/52134205

相关标签: path