将自己数据转化为cifar10支持的lmdb

Posted Hanson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将自己数据转化为cifar10支持的lmdb相关的知识,希望对你有一定的参考价值。

大家都知道,在caffe里面,要运行cifar10的例子就得先由cifar10的数据库。由于caffe为了提高运行效率,减少磁盘寻道时间等,统一了数据接口(lmdb,leveldb)。

首先,看一下cafferoot/data/cifar10(cafferoot指的是自己caffe安装的根目录)下面的get_cifar10.sh

技术分享

 

可见其下载的是bin格式的图片,然后通过cafferoot/examples/cifar10/create_cifar10.sh将bin文件转化为lmdb格式。

那么这样的问题来了,由于,cifar10由官网提供了2进制的bin文件,如果我们想训练自己的模型呢?如果我们想加进自己的图片呢。所以,一个保持和官网cifar10同步的将传统的jpg、png等格式转为bin格式的程序应用而生。

 

进入正题

1,cifar10的bin数据格式

image 的大小为32*32,flag为0-9,共10类,使用的是cifar-10数据集

二进制数据格式为flag,R(1024),G(1024),B(1024),每个通道按行排列

2,读取cifar10的bin文件,将bin文件中数据转化为图片并显示

[cpp] view plain copy
 
  1. void read_cifar_bin(string file_address,vector<Mat>& image,vector<int>& flag)  
  2. {     
  3.     int width = 32, height = 32;//注意这个数值,根据自己样本的大小进行修改,重要的事情说三遍  
  4.     ifstream fin(file_address, ios::binary);  
  5.     while (!fin.eof())  
  6.     {  
  7.         char flag_tmp;  
  8.         unsigned char tmp;  
  9.         Mat image_tmp(width, height, CV_8UC3);  
  10.         fin.read((char *)&flag_tmp, sizeof(flag_tmp));  
  11.           
  12.         for (int j = 2; j >=0; j--)  
  13.         {  
  14.             for (int r = 0; r < image_tmp.rows; r++)  
  15.             for (int c = 0; c < image_tmp.cols; c++)  
  16.             {  
  17.                 fin.read((char *)&tmp, sizeof(tmp));  
  18.                 image_tmp.at<Vec3b>(r, c)[j] = tmp;  
  19.             }  
  20.         }  
  21.         image.push_back(image_tmp);  
  22.         flag.push_back(flag_tmp);  
  23.   
  24.     }  
  25.   
  26. }  

3,将自己的jpg,png等传统格式转化为cifar10支持的bin文件

 

[cpp] view plain copy
 
  1. void write_cifar_bin(string file_address, vector<string>& image_address, vector<int>& flag)  
  2. {  
  3.   
  4.     ofstream fout(file_address, ios::binary);  
  5.     for (size_t i = 0; i < image_address.size(); i++)  
  6.     {  
  7.         Mat image_tmp = imread(image_address[i], 1);  
  8.         resize(image_tmp, image_tmp, Size(32, 32));  
  9.   
  10.           
  11.         int pix[1024];  
  12.         char flag_tmp = flag[i];  
  13.         fout.write((char *)&flag_tmp, sizeof(flag_tmp));  
  14.   
  15.         for (int j = 2; j >= 0; j--)  
  16.         {  
  17.             for (int r = 0; r < image_tmp.rows; r++)  
  18.             for (int c = 0; c < image_tmp.cols; c++)  
  19.             {  
  20.                 unsigned char tmp = image_tmp.at<Vec3b>(r, c)[j];  
  21.                 fout.write((char *)&tmp, sizeof(tmp));  
  22.                   
  23.             }  
  24.         }  
  25.   
  26.     }  
  27.   
  28. }  

 

4,将bin转为图片的测试,并用OpenCV显示

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     string file_address = "data_batch_1.bin";  
  4.     vector<Mat> image;  
  5.     vector<int>flag;  
  6.     read_cifar_bin(file_address, image, flag);  
  7.     imshow("test", image[5000]);//随便需要显示的图像。可以跟改[]中数据进行验证  
  8.     waitKey();  
  9.     return 0;  
  10. }  

5,将bin转为图片的测试,并保存为jpg,并且保存相应的flag

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     string file_address = "data_batch_1.bin";  
  4.     vector<Mat> image;  
  5.     vector<int>flag;  
  6.     read_cifar_bin(file_address, image, flag);  
  7.     ofstream mydata_batch_1("mydata_batch_1.txt");  
  8.     for (int i = 0; i < image.size(); i++)  
  9.     {  
  10.     char buffer[50];  
  11.     char address[100] = ".\\data_batch_1\\";  
  12.     _itoa(i, buffer, 10);  
  13.     imwrite(strcat(address, strcat(buffer, ".jpg")), image[i]);  
  14.     mydata_batch_1 << address << buffer <<".jpg"<< " " << flag[i] << endl;  
  15.     cout << i << endl;  
  16.     waitKey(1);  
  17.     }     
  18.     return 0;  
  19. }  

6,将图像转为bin

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     string file_address = "mydata_batch_1.bin";  
  4.     vector<string> image_address;  
  5.     vector<int> flag;  
  6.   
  7.     ifstream finSample("mydata_batch_1.txt");  
  8.     char buf[100], buftmp[50], flagtmp[10];  
  9.     while (!finSample.eof())  
  10.     {  
  11.         finSample.getline(buf, sizeof(buf));  
  12.         sscanf(buf, "%s %s", buftmp, flagtmp);  
  13.         int tmp=atoi(flagtmp);  
  14.         image_address.push_back(buftmp);  
  15.         flag.push_back(tmp);  
  16.   
  17.     }  
  18.     write_cifar_bin(file_address, image_address, flag);  
  19.     return 0;  
  20. }  

7,实验测试

(1)【步骤4】将cifar10的data_batch_1.bin转化为图像的测试,从左到右依次为image[0],image[5000],image[9999](cifar10每个batch有10000个图像,所以是0-9999)

技术分享

 

(2) 【步骤5】将cifar10的data_batch_1.bin转化为图像,并保存在jpg格式的测试。

技术分享

(3)【步骤6】将第二步生成的jpg转化为bin文件, 程序运行后将生成mydata_batch_1.bin,可以看到和原始的data_batch_1.bin有着同样的大小。

技术分享

 

那么到底这个和原始的一样不一样呢?我们还是使用步骤4的程序进行测试,同样的还是测试image[0],image[5000],image[9999],从下图可以看出和原始的bin的数据是一样的。

技术分享

 

有了上面的2个转化程序,就可以转化自己的图像了,then let‘s make some noise!

 






以上是关于将自己数据转化为cifar10支持的lmdb的主要内容,如果未能解决你的问题,请参考以下文章

使用ResNet18实现CIFAR10数据集的训练

TFRecord文件的读写

制作自己的python版本的类CIFAR10数据集

制作自己的python版本的类CIFAR10数据集

LeNet模型对CIFAR-10数据集分类pytorch

TensorFlow 制作自己的TFRecord数据集