发现网上大把都是用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;
}

C++基于文件流和armadillo读取mnist的更多相关文章

  1. JS通过使用PDFJS实现基于文件流的预览功能

    需求: 使用JS实现PDF文件预览功能 备选方案: 使用ViewerJS,官网  http://viewerjs.org/ 使用PDFJS,官网  https://mozilla.github.io/ ...

  2. C#循环读取文件流,按行读取

    public Dictionary<string,string> GetSourceDisksElements(String section) { section = "[&qu ...

  3. 使用C#处理基于比特流的数据

    使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...

  4. c语言中的文件流

    一.打开和关闭文件 #include int main( void ) { FILE* pReadFile = fopen( "E:\\mytest.txt", "r&q ...

  5. Linux 文件流管理

    1. 打开/关闭文件 1). 打开文件 / fopen 作用: 打开一个文件,将其与文件流联系起来,方便后续的操作 头文件: #include <stdio.h> 函数原型: FILE * ...

  6. 第十四周总结 Io之文件流

    I/O相关 输入/输出 流(数据流动) 数据流动的方向 读数据(输入input) 写数据(输出output) 文件流 字符流 数据流 对象流 网络流.... 1.什么叫文件 一种电脑的存储方式 文件有 ...

  7. koa2基于stream(流)进行文件上传和下载

    阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...

  8. 文件_ _android从资源文件中读取文件流并显示的方法

    ======== 1   android从资源文件中读取文件流并显示的方法. 在android中,假如有的文本文件,比如TXT放在raw下,要直接读取出来,放到屏幕中显示,可以这样: private ...

  9. FileStream文件流的读取和写入(为以后聊天工具的设计基础)

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

随机推荐

  1. RabbitMQ镜像队列集群搭建、与SpringBoot整合

    镜像模式 集群模式非常经典的就是Mirror镜像模式,保证100%数据不丢失,在实际工作中也是用的最多的,并且实现集群比较的简单. Mirror镜像队列,目的是为了保证 RabbitMQ 数据的高可靠 ...

  2. Redis的常用淘汰策略以及算法实现

    一.Redis的内存配置 1,Redis配置内存为多少合适? 默认:如果不设置最大内存大小或者设置最大内存大小为0,在64为操作系统下不限制内存大小,在32位操作系统下最多使用3GB内存. 极限情况: ...

  3. dex、apk完整性校验

    对Dex进行完整性的检查,可通过CRC,或者Hash值.可将校验值放到String资源文件里,或者放到服务器中. 在代码中完成校验值对比逻辑,此部分代码后续不能再改变,否则CRC值会发生变化: 从生成 ...

  4. Java中的名称命名规范:

    Java中的名称命名规范:(不遵守,也不会出现编译的错误) 包名:多单词组成时所有字母都小写:xxxyyyzzz 类名.接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz 变量名.方法名: ...

  5. get和post的区别主要有以下几方面

    1.url可见性: get,参数url可见: post,url参数不可见 2.数据传输上: get,通过拼接url进行传递参数: post,通过body体传输参数 3.缓存性: get请求是可以缓存的 ...

  6. 如何动态生成EasyUI的表头

    需求 前几天遇到了这样一个需求,在页面上展示一组数据,但是表头不固定,需要动态加载出来.比如这次查询表头有[姓名][年龄],可能下次查询表头就变成了[姓名][年龄][性别]. 思路简介 我刚刚接手这个 ...

  7. C++单重继承分析

    code[class*="language-"], pre[class*="language-"] { color: rgba(51, 51, 51, 1); ...

  8. 【Spring Cloud & Alibaba全栈开源项目实战】:SpringBoot整合ELK实现分布式登录日志收集和统计

    一. 前言 其实早前就想计划出这篇文章,但是最近主要精力在完善微服务.系统权限设计.微信小程序和管理前端的功能,不过好在有群里小伙伴的一起帮忙反馈问题,基础版的功能已经差不多,也在此谢过,希望今后大家 ...

  9. 第2课:操作系统网络配置【DevOps基础培训】

    第2课:操作系统网络配置 --DevOps基础培训 1. DNS配置 1.1 什么是DNS? 域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务.它作为将域名和IP ...

  10. windows环境下抓密码总结

    在线抓密码 1.mimikatz privilege::debug token::whoami token::elevate lsadump::sam mimikatz.exe "privi ...