在深度学习入门过程中,一般以mnist数据集入手,因此经常需要将自己的数据集压缩成mnist格式形式带入源代码中进行训练,同时mnist数据集为二值化图像,如果自己的数据集为RGB三通道图像,应该怎么压缩数据集图像成为mnist格式,c++脚本代码如下:
1、头文件
#pragma once
#ifndef IMAGE_TO_BINARYDATA_H_
#define IMAGE_TO_BINARYDATA_H_
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace std;
class Image2BinaryData
{
public:
int Height;
int Width;
public:
Image2BinaryData(int x, int y) :Height(x), Width(y) {}
~Image2BinaryData() {}
void ReverseInt(ofstream &file, int i);
vector<string> getFileLists(string file_folder); //获取文件夹下的图片名称
string getFileName(string &filename); //从文件的绝对路径当中得到文件名
void ReadImage(string filefolder, vector<string> &img_Lists, vector<int> &img_Labels, vector<cv::Mat> &ImagesMat);
void Image2BinaryFile(string filefolder, vector<cv::Mat> &ImagesMat, vector<int> & img_Labels);
void Label2BinaryFile(string filefolder, vector<int> &img_Labels);
};
#endif // !IMAGE_TO_BINARYDATA_H_
2、将数据集图像压缩成二进制mnist数据集格式
#include "Image_to_BinaryData.h"
#include <atlfile.h>
#include <cstdlib>
#include <fstream>
using namespace cv;
//#define _CRT_SECURE_NO_WARNINGS
//#pragma warning(disable:4996)
void Image2BinaryData::ReverseInt(ofstream &file, int i)
{
uchar ch1 = (uchar)(i >> 24);
uchar ch2 = (uchar)((i << 8) >> 24);
uchar ch3 = (uchar)((i << 16) >> 24);
uchar ch4 = (uchar)((i << 24) >> 24);
file.write((char*)&ch1, sizeof(ch4));
file.write((char*)&ch2, sizeof(ch3));
file.write((char*)&ch3, sizeof(ch2));
file.write((char*)&ch4, sizeof(ch1));
}
vector<string> Image2BinaryData::getFileLists(string file_folder)
{
/*
param
file_folder: 文件夹路径
*/
file_folder += "\\*.*";
const char *mystr = file_folder.c_str();
vector<string> flist;
string lineStr;
vector<string> extendName; //设置文件扩展名
extendName.push_back("JPG");
extendName.push_back("jpg");
extendName.push_back("bmp");
extendName.push_back("png");
extendName.push_back("tiff");
HANDLE file;
WIN32_FIND_DATA fileData;
char line[1024];
wchar_t fn[1000];
mbstowcs(fn, mystr, 999); //把多字符转换成宽字符
file = FindFirstFile(fn, &fileData);
FindNextFile(file, &fileData);
while (FindNextFile(file, &fileData))
{
wcstombs(line, (const wchar_t*)fileData.cFileName, 259); //将宽字符转换成多字符
lineStr = line;
// remove the files which are not images
for (int i = 0; i < 4; i++)
{
if (lineStr.find(extendName[i]) < 999)
{
flist.push_back(lineStr);
break;
}
}
}
return flist;
}
string Image2BinaryData::getFileName(string & filename)
{
int iBeginIndex = filename.find_last_of("\\") + 1;
int iEndIndex = filename.length();
return filename.substr(iBeginIndex, iEndIndex - iBeginIndex);
cout << "Done!" << endl;
}
void Image2BinaryData::ReadImage(string filefolder, vector<string>& img_Lists, vector<int>& img_Labels, vector<cv::Mat> &ImagesMat)
{
const int size_list = img_Lists.size();
for (int i = 0; i < size_list; ++i) {
string curPath = filefolder + "\\" + img_Lists[i];
Mat image = imread(curPath, IMREAD_UNCHANGED);
ImagesMat.push_back(image);
char label = img_Lists[i][0];
img_Labels[i] = label - '0';
printf("正在读取图片,请稍等: %.2lf%%\r", i*100.0 / (size_list - 1));
}
printf("\n图片读取完毕!\n\n");
}
void Image2BinaryData::Image2BinaryFile(string filefolder, vector<cv::Mat>& ImagesMat, vector<int>& img_Labels)
{
ofstream file(filefolder, ios::binary);
int idx = filefolder.find_last_of("\\") + 1;
string subName = filefolder.substr(idx);
if (file.is_open()) {
cout << subName << "文件创建成功." << endl;
int magic_number = 2051;
int number_of_images = img_Labels.size();
int n_rows = Height;
int n_cols = Width;
ReverseInt(file, magic_number);
ReverseInt(file, number_of_images);
ReverseInt(file, n_rows);
ReverseInt(file, n_cols);
cout << "需要转换的图片数为: " << ImagesMat.size() << endl;
for (int i = 0; i < ImagesMat.size(); ++i) {
/*vector<cv::Mat>rgb_vec;
Mat Img_r, Img_g, Img_b;
split(ImagesMat[i], rgb_vec);
Img_r = rgb_vec[0];
Img_g = rgb_vec[1];
Img_b = rgb_vec[2];*/
for (int r = 0; r < n_rows; ++r) {
for (int c = 0; c < n_cols; ++c) {
// Vec3b tmp; //定义三通道像素值变量
uchar tmp;
//tmp[0] = Img_r.at<uchar>(r, c); //Blue
//tmp[1] = Img_g.at<uchar>(r, c); //Green
//tmp[2] = Img_b.at<uchar>(r, c); //Red
//tmp = ImagesMat[i].at<Vec3b>(r, c);
//tmp = ImagesMat[i].at<Vec3b>(r, c); //制作三通道图片
tmp = ImagesMat[i].at<uchar>(r, c);//制作单通道图片
file.write((char*)&tmp, sizeof(tmp));
}
}
printf("图片正在转换,请稍等......%.2lf%%\r", i*100.0 / (ImagesMat.size() - 1));
}
printf("\n******转换完成!******\n\n");
}
else
cout << subName << "文件创建失败." << endl << endl;
if (file.is_open())
file.close();
return;
}
void Image2BinaryData::Label2BinaryFile(string filefolder, vector<int>& img_Labels)
{
ofstream file(filefolder, ios::binary);
int idx = filefolder.find_last_of("\\") + 1;
string subName = filefolder.substr(idx);
if (file.is_open()) {
cout << subName << "文件创建成功." << endl;
int magic_number = 2049;
int number_of_images = img_Labels.size();
ReverseInt(file, magic_number);
ReverseInt(file, number_of_images);
cout << "需要转换的标签数为: " << img_Labels.size() << endl;
for (int i = 0; i < img_Labels.size(); ++i) {
uchar tmp = (uchar)img_Labels[i];
file.write((char*)&tmp, sizeof(tmp));
printf("标签正在转换,请稍等......%.2lf%%\r", i*100.0 / (img_Labels.size() - 1));
}
printf("\n******转换完成!******\n");
}
else
cout << subName << "文件创建失败." << endl;
if (file.is_open())
file.close();
return;
}
3、解压MNIST数据集图像
#include "Image_to_BinaryData.h"
int main()
{
Image2BinaryData IBD(28, 28); //设置图片大小(Height,Width)
/*------------生成训练集文件--------------------------*/
printf("----------生成训练集文件-------------\n");
string trainfilefolder = "D:\\picture\\test2\\num1\\train"; //训练图片文件路径
vector<string> trainfileLists = IBD.getFileLists(trainfilefolder); //获得文件名列表
const int train_size_list = trainfileLists.size();
cout << "Images Number: " << train_size_list << endl; //输出文件个数
string trainimagebinfilepath = "D:\\picture\\test2\\num1\\train-images-idx3-ubyte"; //训练图片转换保存路径
string trainlabelbinfilepath = "D:\\picture\\test2\\num1\\train-labels-idx1-ubyte"; //训练标签转换保存路径
vector<cv::Mat> TrainImagesMat; //用来存储训练图片像素值
vector<int> train_image_labels(train_size_list); //用来存储训练类标签列表
IBD.ReadImage(trainfilefolder, trainfileLists, train_image_labels, TrainImagesMat); //读取训练图片
IBD.Image2BinaryFile(trainimagebinfilepath, TrainImagesMat, train_image_labels); //训练图片转二进制文件
IBD.Label2BinaryFile(trainlabelbinfilepath, train_image_labels); //训练标签转二进制文件
/*------------生成测试集文件--------------------------*/
printf("\n\n----------生成测试集文件-------------\n");
string testfilefolder = "D:\\picture\\test2\\num1\\test"; //测试图片文件路径
vector<string> testfileLists = IBD.getFileLists(testfilefolder); //获得文件名列表
const int test_size_list = testfileLists.size();
cout << "Images Number: " << test_size_list << endl; //输出文件个数
string testimagebinfilepath = "D:\\picture\\test2\\num1\\t10k-images-idx3-ubyte"; //测试图片转换保存路径
string testlabelbinfilepath = "D:\\picture\\test2\\num1\\t10k-labels-idx1-ubyte"; //测试标签转换保存路径
vector<cv::Mat> TestImagesMat; //用来存储测试图片像素值
vector<int> test_image_labels(test_size_list); //用来存储测试类标签列表
IBD.ReadImage(testfilefolder, testfileLists, test_image_labels, TestImagesMat); //读取测试图片
IBD.Image2BinaryFile(testimagebinfilepath, TestImagesMat, test_image_labels); //测试图片转二进制文件
IBD.Label2BinaryFile(testlabelbinfilepath, test_image_labels); //测试标签转二进制文件
system("Pause");
return 0;
}