1.源碼實現
#include <iostream>
#include <string>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
//小端存儲轉換
unsigned int reverseInt(unsigned int i)
{
unsigned char c1, c2, c3, c4;
c1 = i & 0xff;
c2 = (i >> 8) & 0xff;
c3 = (i >> 16) & 0xff;
c4 = (i >> 24) & 0xff;
return ((unsigned int)c1 << 24) + ((unsigned int)c2 << 16) + ((unsigned int)c3 << 8) + c4;
}
Mat read_mnist_image(const string fileName)
{
unsigned int magic_number = 0;
unsigned int number_of_images = 0;
unsigned int n_rows = 0;
unsigned int n_cols = 0;
Mat DataMat;
ifstream file(fileName, ios::binary);
if(file.is_open())
{
cout << "成功打開圖像集..." << endl;
file.read((char *)&magic_number, sizeof(magic_number)); //幻數(文件格式)
file.read((char *)&number_of_images, sizeof(number_of_images)); //圖片總數
file.read((char *)&n_rows, sizeof(n_rows)); //每個圖像的行數
file.read((char *)&n_cols, sizeof(n_cols)); //每個圖像的列數
magic_number = reverseInt(magic_number);
number_of_images = reverseInt(number_of_images);
n_rows = reverseInt(n_rows);
n_cols = reverseInt(n_cols);
cout << "幻數(文件格式): " << magic_number << endl;
cout << "圖片總數: " << number_of_images << endl;
cout << "每個圖像的行數: " << n_rows << endl;
cout << "每個圖像的列數: " << n_cols << endl;
cout << "開始讀取Image數據..." << endl;
DataMat = Mat::zeros(number_of_images, n_rows*n_cols, CV_32FC1);
for(int i=0; i<number_of_images; i++)
{
for(int j=0; j<n_rows*n_cols; j++)
{
unsigned char temp = 0;
file.read((char *)&temp, sizeof(temp));
float pixel = float(temp);
DataMat.at<float>(i, j) = pixel;
}
}
cout << "讀取Image數據完畢..." << endl;
}
file.close();
return DataMat;
}
Mat read_mnist_label(const string fileName)
{
unsigned int magic_number = 0;
unsigned int number_of_items = 0;
Mat LabelMat;
ifstream file(fileName, ios::binary);
if(file.is_open())
{
cout << "成功打開標籤集..." << endl;
file.read((char *)&magic_number, sizeof(magic_number)); //幻數(文件格式)
file.read((char *)&number_of_items, sizeof(number_of_items)); //標籤總數
magic_number = reverseInt(magic_number);
number_of_items = reverseInt(number_of_items);
cout << "幻數(文件格式): " << magic_number << endl;
cout << "標籤總數: " << number_of_items << endl;
cout << "開始讀取Label數據..." << endl;
LabelMat = Mat::zeros(number_of_items, 1, CV_32SC1);
for(int i=0; i<number_of_items; i++)
{
unsigned char temp = 0;
file.read((char *)&temp, sizeof(temp));
LabelMat.at<unsigned int>(i, 0) = (unsigned int)temp;
}
cout << "讀取Label數據完畢..." << endl;
}
file.close();
return LabelMat;
}
int main()
{
string train_images_path = "./train-images-idx3-ubyte";
string train_labels_path = "./train-labels-idx1-ubyte";
//讀取標籤數據集
Mat train_labels = read_mnist_label(train_labels_path);
//讀取圖像數據集
Mat train_images = read_mnist_image(train_images_path);
//打印第二個標籤
Mat label1 = train_labels.rowRange(1, 2);
cout << "第二個標籤: " << label1 << endl;
//取第二張圖片
Mat img1 = train_images.rowRange(1, 2);
//改變形狀爲(28, 28)
img1 = img1.reshape(1, 28);
//保存圖片
imwrite("mnist_train_1.jpg", img1);
return 0;
}
2.編譯源碼
$ g++ -o test test.cpp -std=c++11 -I/usr/local/include -L/usr/local/lib -lopencv_core -lopencv_highgui -lopencv_imgproc -Wl,-rpath=/usr/local/lib
3.運行程序
$ ./test
成功打開標籤集...
幻數(文件格式): 2049
標籤總數: 60000
開始讀取Label數據...
讀取Label數據完畢...
成功打開圖像集...
幻數(文件格式): 2051
圖片總數: 60000
每個圖像的行數: 28
每個圖像的列數: 28
開始讀取Image數據...
讀取Image數據完畢...
第二個標籤: [0]
4.結果展示