C++基于文件流與armadillo讀取mnist示例詳解
前言
發(fā)現(xiàn)網(wǎng)上大把都是用python讀取mnist的,用C++大都是用opencv讀取的,但我不怎么用opencv,因此自己摸索了個(gè)使用文件流讀取mnist的方法,armadillo僅作為儲(chǔ)存矩陣的一種方式。
1. mnist文件
首先避坑,這些文件要解壓。

官網(wǎng)截圖可知,文件頭很簡(jiǎn)單,只有若干個(gè)32位整數(shù),MSB,像素和標(biāo)簽均是無符號(hà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)行對(duì)比),剩下的就是文件的內(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ù),但是請(qǐng)標(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++示例分析內(nèi)聯(lián)函數(shù)與引用變量及函數(shù)重載的使用
為了消除函數(shù)調(diào)用的時(shí)空開銷,C++ 提供一種提高效率的方法,即在編譯時(shí)將函數(shù)調(diào)用處用函數(shù)體替換,類似于C語言中的宏展開。這種在函數(shù)調(diào)用處直接嵌入函數(shù)體的函數(shù)稱為內(nèi)聯(lián)函數(shù)(Inline Function),又稱內(nèi)嵌函數(shù)或者內(nèi)置函數(shù)2022-08-08
C++實(shí)現(xiàn)簡(jiǎn)單計(jì)算器
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05
VC++文件監(jiān)控之FindFirstChangeNotification
因?yàn)镽eadDirectoryChangesW 上次測(cè)試發(fā)現(xiàn)不能多級(jí)目錄監(jiān)控,所以嘗試用FindFirstChangeNotification來實(shí)施文件監(jiān)控,需要的朋友可以參考下2019-04-04

