1. 程式人生 > >將自己數據轉化為cifar10支持的lmdb

將自己數據轉化為cifar10支持的lmdb

顯示 c++ track div ifs cat 自己的 align blog

大家都知道,在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. for (int j = 2; j >=0; j--)
  12. {
  13. for (int r = 0; r < image_tmp.rows; r++)
  14. for (int c = 0; c < image_tmp.cols; c++)
  15. {
  16. fin.read((char *)&tmp, sizeof(tmp));
  17. image_tmp.at<Vec3b>(r, c)[j] = tmp;
  18. }
  19. }
  20. image.push_back(image_tmp);
  21. flag.push_back(flag_tmp);
  22. }
  23. }

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. ofstream fout(file_address, ios::binary);
  4. for (size_t i = 0; i < image_address.size(); i++)
  5. {
  6. Mat image_tmp = imread(image_address[i], 1);
  7. resize(image_tmp, image_tmp, Size(32, 32));
  8. int pix[1024];
  9. char flag_tmp = flag[i];
  10. fout.write((char *)&flag_tmp, sizeof(flag_tmp));
  11. for (int j = 2; j >= 0; j--)
  12. {
  13. for (int r = 0; r < image_tmp.rows; r++)
  14. for (int c = 0; c < image_tmp.cols; c++)
  15. {
  16. unsigned char tmp = image_tmp.at<Vec3b>(r, c)[j];
  17. fout.write((char *)&tmp, sizeof(tmp));
  18. }
  19. }
  20. }
  21. }

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. ifstream finSample("mydata_batch_1.txt");
  7. char buf[100], buftmp[50], flagtmp[10];
  8. while (!finSample.eof())
  9. {
  10. finSample.getline(buf, sizeof(buf));
  11. sscanf(buf, "%s %s", buftmp, flagtmp);
  12. int tmp=atoi(flagtmp);
  13. image_address.push_back(buftmp);
  14. flag.push_back(tmp);
  15. }
  16. write_cifar_bin(file_address, image_address, flag);
  17. return 0;
  18. }

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