C++基于文件流和armadillo读取mnist
发现网上大把都是用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的更多相关文章
- JS通过使用PDFJS实现基于文件流的预览功能
需求: 使用JS实现PDF文件预览功能 备选方案: 使用ViewerJS,官网 http://viewerjs.org/ 使用PDFJS,官网 https://mozilla.github.io/ ...
- C#循环读取文件流,按行读取
public Dictionary<string,string> GetSourceDisksElements(String section) { section = "[&qu ...
- 使用C#处理基于比特流的数据
使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...
- c语言中的文件流
一.打开和关闭文件 #include int main( void ) { FILE* pReadFile = fopen( "E:\\mytest.txt", "r&q ...
- Linux 文件流管理
1. 打开/关闭文件 1). 打开文件 / fopen 作用: 打开一个文件,将其与文件流联系起来,方便后续的操作 头文件: #include <stdio.h> 函数原型: FILE * ...
- 第十四周总结 Io之文件流
I/O相关 输入/输出 流(数据流动) 数据流动的方向 读数据(输入input) 写数据(输出output) 文件流 字符流 数据流 对象流 网络流.... 1.什么叫文件 一种电脑的存储方式 文件有 ...
- koa2基于stream(流)进行文件上传和下载
阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...
- 文件_ _android从资源文件中读取文件流并显示的方法
======== 1 android从资源文件中读取文件流并显示的方法. 在android中,假如有的文本文件,比如TXT放在raw下,要直接读取出来,放到屏幕中显示,可以这样: private ...
- FileStream文件流的读取和写入(为以后聊天工具的设计基础)
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...
随机推荐
- 全真教程:Windows环境Jupyter Notebook安装、运行和工作文件夹配置
全真教程:Windows环境Jupyter Notebook安装.运行和工作文件夹配置 @ 目录 全真教程:Windows环境Jupyter Notebook安装.运行和工作文件夹配置 一.Jupyt ...
- python基础学习之函数基础和部分内置函数
在函数调用的时候,必备参数必须要传入 函数定义: def 函数名: 代码块pass return 返回值 函数名命名规则: 字母.数字和下划线组成,和变量命名规则一致 pass在这里表示什么都没有 ...
- Bi-shoe and Phi-shoe LightOJ - 1370(数论+素数筛)
题目链接:https://vjudge.net/problem/LightOJ-1370 题意:给你N个欧拉函数值,找出每一个大于等于该欧拉函数值的数,并且要求相加和最小. 题解:因为素数i的欧拉函数 ...
- 时间同步chrony,最全最细
时间同步服务 多主机协作工作时,各个主机的时间同步很重要,时间不一致会造成很多重要应用的故障,如:加密协 议,日志,集群等, 利用NTP(Network Time Protocol) 协议使网络中的各 ...
- 操作系统实验(一)-Shell编程
操作系统实验:Shell编程 emmmmm,实验前老师发了一份实验说明,里面有教怎么配置虚拟机Ubuntu.这里就不做过多叙述,需要说明的是,kali和ubuntu都可以以shell运行这个C语言程序 ...
- 如何提高Web应用系统的性能?
随着互联网信息技术的发展,人们逐渐开始习惯在网络上交友.购物.学习.娱乐.工作,甚至是找工作.因此市场对网站的响应速度也提出了新的要求,提高Web应用系统的性能成为急需解决的关键问题.本文将会给出一些 ...
- Hadoop集群--linux虚拟机Hadoop安装与配置、克隆虚拟机
Hadoop集群 第四章 Hadoop安装与配置.克隆虚拟机 一.Hadoop安装与配置 1.将hadoop安装包通过Xftp传输到虚拟机的/software目录下 2.进入/software目录下, ...
- vue实现拖拽排序
基于vue实现列表拖拽排序的效果 在日常开发中,特别是管理端,经常会遇到要实现拖拽排序的效果:这里提供一种简单的实现方案. 此例子基于vuecli3 首先,我们先了解一下js原生拖动事件: 在拖动目标 ...
- Golang 基于Prometheus Node_Exporter 开发自定义脚本监控
Golang 基于Prometheus Node_Exporter 开发自定义脚本监控 公司是今年决定将一些传统应用从虚拟机上迁移到Kubernetes上的,项目多而乱,所以迁移工作进展缓慢,为了建立 ...
- redis的主从复制(哨兵模式)
p.p1 { margin: 0; font: 10px ".SF NS Text" } Master以写为主,Slave以读为主 读写分离 容灾恢复 一.一主多从 配置文件修改: ...