mnist本身是将数字手写体图像,归一化后信息合成的文档,分训练集和测试集两部分,每部分包含图片和标签两个文档,本文使用C++写的Demo将文档解码,并通过opencv将数据存储为常规的图像文档。源码下载地址:https://github.com/zacSuo/mnist
t10k-images.idx3-ubyte
t10k-labels.idx1-ubyte
train-images.idx3-ubyte
train-labels.idx1-ubyte
使用说明
环境要求
visual studio 2012及以上版本
opencv 2.4及以上版本 配置 启动前先通过项目属性,设置本地opencv的路径。
执行结果
在目录的两个文档夹,分别将测试集(test_images)和训练集(train_images)的图片保存到其中。
进程说明
解码图像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
int (std ::string filename, std ::vector <cv::Mat> &vec) { int number_of_images = 0 ; std ::ifstream file (filename, std ::ios::binary) ; if (file.is_open()) { int magic_number = 0 ; int n_rows = 0 ; int n_cols = 0 ; file.read((char *)&magic_number, sizeof (magic_number)); magic_number = ReverseInt(magic_number); file.read((char *)&number_of_images, sizeof (number_of_images)); number_of_images = ReverseInt(number_of_images); file.read((char *)&n_rows, sizeof (n_rows)); n_rows = ReverseInt(n_rows); file.read((char *)&n_cols, sizeof (n_cols)); n_cols = ReverseInt(n_cols); for (int i = 0 ; i < number_of_images; ++i) { cv::Mat tp = cv::Mat::zeros(n_rows, n_cols, CV_8UC1); for (int r = 0 ; r < n_rows; ++r) { for (int c = 0 ; c < n_cols; ++c) { unsigned char temp = 0 ; file.read((char *)&temp, sizeof (temp)); tp.at<uchar>(r, c) = (int )temp; } } vec.push_back(tp); } file.close(); } return number_of_images; }
解码图像对应数值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
void read_Mnist_Label (std ::string filename, std ::vector <int > &vec) { std ::ifstream file (filename, std ::ios::binary) ; if (file.is_open()) { int magic_number = 0 ; int number_of_images = 0 ; int n_rows = 0 ; int n_cols = 0 ; file.read((char *)&magic_number, sizeof (magic_number)); magic_number = ReverseInt(magic_number); file.read((char *)&number_of_images, sizeof (number_of_images)); number_of_images = ReverseInt(number_of_images); for (int i = 0 ; i < number_of_images; ++i) { unsigned char temp = 0 ; file.read((char *)&temp, sizeof (temp)); vec[i] = (int )temp; } file.close(); } }
生成图像文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
int decodeDatabase (std ::string filenameImages,std ::string filenameLabels,std ::string imagesPathSave) { std ::vector <cv::Mat> vec_train_images; int number_of_train_images = read_Mnist(filenameImages, vec_train_images); std ::vector <int > vec_train_labels(number_of_train_images); read_Mnist_Label(filenameLabels, vec_train_labels); if (vec_train_images.size() != vec_train_labels.size()) { std ::cout << "parse MNIST train file error" << std ::endl ; return -1 ; } int count_digits[10 ]; std ::fill(&count_digits[0 ], &count_digits[0 ] + 10 , 0 ); for (int i = 0 ; i < vec_train_images.size(); i++) { int number = vec_train_labels[i]; std ::string image_name = GetImageName(number, count_digits); image_name = imagesPathSave + image_name + ".jpg" ; cv::imwrite(image_name, vec_train_images[i]); } return 0 ; }
每个数值各选20张图像合并成一个图像文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
int mergeSomeImages () { std ::string images_path = ".././mnistFile/train_images/" ; int width = 28 * 20 ; int height = 28 * 10 ; cv::Mat dst (height, width, CV_8UC1) ; for (int i = 0 ; i < 10 ; i++) { for (int j = 1 ; j <= 20 ; j++) { int x = (j-1 ) * 28 ; int y = i * 28 ; cv::Mat part = dst(cv::Rect(x, y, 28 , 28 )); std ::string str = std ::to_string(j); if (j < 10 ) str = "0000" + str; else str = "000" + str; str = std ::to_string(i) + "_" + str + ".jpg" ; std ::string input_image = images_path + str; cv::Mat src = cv::imread(input_image, 0 ); if (src.empty()) { fprintf (stderr , "read image error: %sn" , input_image.c_str()); return -1 ; } src.copyTo(part); } } std ::string output_image = images_path + "result.png" ; cv::imwrite(output_image, dst); return 0 ; }
原文链接 大专栏 https://www.dazhuanlan.com/2019/08/25/5d61bcc0916e4/