C++基于文件流與armadillo讀取mnist示例詳解
前言
發(fā)現(xiàn)網(wǎng)上大把都是用python讀取mnist的,用C++大都是用opencv讀取的,但我不怎么用opencv,因此自己摸索了個(gè)使用文件流讀取mnist的方法,armadillo僅作為儲(chǔ)存矩陣的一種方式。
1. mnist文件
首先避坑,這些文件要解壓。
官網(wǎng)截圖可知,文件頭很簡單,只有若干個(gè)32位整數(shù),MSB,像素和標(biāo)簽均是無符號字節(jié)(即unsigned char)可以先讀取文件頭,再讀取剩下的部分。
2. 讀取文件頭
我覺得沒什么必要啊,直接跳過不行嗎
文件頭都是32位,那就整四個(gè)unsigned char唄。
uchar a, b, c, d; File >> a >> b >> c >> d;
這樣a、b、c、d就保存了一個(gè)整數(shù)。
x = ((((a * 256) + b) * 256) + c) * 256 + d;
然后就得到了唄。
看每個(gè)文件有多少文件頭,就操作幾次(并可以順便與官方的magic number進(jìn)行對比),剩下的就是文件的內(nèi)容了。
3. 讀取內(nèi)容
這部分可以依照之前的方法,一次讀取一個(gè)字符,再保存至矩陣當(dāng)中。例如:
uchar a; mat image(28, 28, fill::zeros); // 這是個(gè)矩陣! for(int i = 0; i < 28; i++) //28行28列的圖像懶得改了 for(int j = 0; j < 28; j++) { File >> a; image(i, j) = double(a); }
這樣就讀取了一張圖片。其余以此類推吧。
4. 完整代碼
可以復(fù)制,可以修改,也可以用于商用和學(xué)術(shù),但是請標(biāo)注原作者(就是我)。
mnist.h
#ifndef MNIST_H #define MNIST_H #include<iostream> #include<fstream> #include<armadillo> #define uchar unsigned char using namespace std; using namespace arma; //小端存儲(chǔ)轉(zhuǎn)換 int reverseInt(uchar a, uchar b, uchar c, uchar d); //讀取image數(shù)據(jù)集信息 mat read_mnist_image(const string fileName); //讀取label數(shù)據(jù)集信息 mat read_mnist_label(const string fileName); #endif
mnist.cpp
//mnist.cpp //作者:C艸 #include "mnist.h" int reverseInt(uchar a, uchar b, uchar c, uchar d) { return ((((a * 256) + b) * 256) + c) * 256 + d; } mat read_mnist_image(const string fileName) { fstream File; mat image; File.open(fileName); if (!File.is_open()) // cannot open file { cout << "文件打不開啊" << endl; return mat(0, 0, fill::zeros); } uchar a, b, c, d; File >> a >> b >> c >> d; int magic = reverseInt(a, b, c, d); if (magic != 2051) //magic number wrong { cout << magic; return mat(0, 0, fill::zeros); } File >> a >> b >> c >> d; int num_img = reverseInt(a, b, c, d); File >> a >> b >> c >> d; int num_row = reverseInt(a, b, c, d); File >> a >> b >> c >> d; int num_col = reverseInt(a, b, c, d); // 文件頭讀取完畢 image = mat(num_img, num_col * num_row, fill::zeros); for(int i = 0; i < num_img; i++) for (int j = 0; j < num_col * num_row; j++) { File >> a; image(i, j) = double(a); } return image; } mat read_mnist_label(const string fileName) { fstream File; mat label; File.open(fileName); if (!File.is_open()) // cannot open file { cout << "文件打不開啊" << endl; return mat(0, 0, fill::zeros); } uchar a, b, c, d; File >> a >> b >> c >> d; int magic = reverseInt(a, b, c, d); if (magic != 2049) //magic number wrong { cout << magic; return mat(0, 0, fill::zeros); } File >> a >> b >> c >> d; int num_lab = reverseInt(a, b, c, d); // 文件頭讀取完畢 label = mat(num_lab, 10, fill::zeros); for (int i = 0; i < num_lab; i++) { File >> a; label(i, int(a)) = 1; } return label; }
總結(jié)
到此這篇關(guān)于C++基于文件流與armadillo讀取mnist的文章就介紹到這了,更多相關(guān)C++ armadillo讀取mnist內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言超詳細(xì)講解棧與隊(duì)列實(shí)現(xiàn)實(shí)例
棧和隊(duì)列,嚴(yán)格意義上來說,也屬于線性表,因?yàn)樗鼈円捕加糜诖鎯?chǔ)邏輯關(guān)系為?"一對一"?的數(shù)據(jù),但由于它們比較特殊,因此將其單獨(dú)作為一章,做重點(diǎn)講解2022-03-03Qt專欄之模態(tài)與非模態(tài)對話框的實(shí)現(xiàn)
這篇文章主要介紹了Qt專欄之模態(tài)與非模態(tài)對話框的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04C++深入學(xué)習(xí)之徹底理清重載函數(shù)匹配
C++ 不允許變量重名,但是允許多個(gè)函數(shù)取相同的名字,只要參數(shù)表不同即可,這叫作函數(shù)的重載,下面這篇文章主要給大家介紹了關(guān)于C++深入學(xué)習(xí)之徹底理清重載函數(shù)匹配的相關(guān)資料,需要的朋友可以參考下2019-01-01