当前位置 博文首页 > c艹用户:C++基于文件流和armadillo读取mnist

    c艹用户:C++基于文件流和armadillo读取mnist

    作者:c艹用户 时间:2021-05-09 18:19

    发现网上大把都是用python读取mnist的,用C++大都是用opencv读取的,但我不怎么用opencv,因此自己摸索了个使用文件流读取mnist的方法,armadillo仅作为储存矩阵的一种方式。

    1. mnist文件

    首先避坑,这些文件要解压。
    没有肾么描述
    官网截图可知,文件头很简单,只有若干个32位整数,MSB,像素和标签均是无符号字节(即unsigned char)可以先读取文件头,再读取剩下的部分。

    2. 读取文件头

    我觉得没什么必要啊,直接跳过不行吗
    文件头都是32位,那就整四个unsigned char呗。

    	uchar a, b, c, d;
    	File >> a >> b >> c >> d;
    

    这样a、b、c、d就保存了一个整数。

    x = ((((a * 256) + b) * 256) + c) * 256 + d;
    

    然后就得到了呗。
    看每个文件有多少文件头,就操作几次(并可以顺便与官方的magic number进行对比),剩下的就是文件的内容了。

    3. 读取内容

    这部分可以依照之前的方法,一次读取一个字符,再保存至矩阵当中。例如:

    uchar a;
    mat image(28, 28, fill::zeros); // 这是个矩阵!
    for(int i = 0; i < 28; i++) //28行28列的图像懒得改了
    	for(int j = 0; j < 28; j++)
    	{
    		File >> a;
    		image(i, j) = double(a);
    	}
    

    这样就读取了一张图片。其余以此类推吧。

    4. 完整代码

    可以复制,可以修改,也可以用于商用和学术,但是请标注原作者(就是我)。
    mnist.h

    #ifndef MNIST_H  
    #define MNIST_H
    #include<iostream>
    #include<fstream>
    #include<armadillo>
    
    #define uchar unsigned char
    
    using namespace std;
    using namespace arma;
    
    //小端存储转换
    int reverseInt(uchar a, uchar b, uchar c, uchar d);
    
    //读取image数据集信息
    mat read_mnist_image(const string fileName);
    
    //读取label数据集信息
    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 != 2051) //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;
    }
    
    
    bk
    下一篇:没有了