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

1. mnist文件

首先避坑,这些文件要解压。



官网截图可知,文件头很简单,只有若干个32位整数,MSB,像素和标签均是无符号字节(即unsigned char)可以先读取文件头,再读取剩下的部分。

2. 读取文件头

我觉得没什么必要啊,直接跳过不行吗

文件头都是32位,那就整四个unsigned char呗。

  1. uchar a, b, c, d;
  2. File >> a >> b >> c >> d;

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

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

然后就得到了呗。

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

3. 读取内容

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

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

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

4. 完整代码

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

mnist.h

  1. #ifndef MNIST_H
  2. #define MNIST_H
  3. #include<iostream>
  4. #include<fstream>
  5. #include<armadillo>
  6. #define uchar unsigned char
  7. using namespace std;
  8. using namespace arma;
  9. //小端存储转换
  10. int reverseInt(uchar a, uchar b, uchar c, uchar d);
  11. //读取image数据集信息
  12. mat read_mnist_image(const string fileName);
  13. //读取label数据集信息
  14. mat read_mnist_label(const string fileName);
  15. #endif

mnist.cpp

  1. //mnist.cpp
  2. //作者:C艹
  3. #include "mnist.h"
  4. int reverseInt(uchar a, uchar b, uchar c, uchar d)
  5. {
  6. return ((((a * 256) + b) * 256) + c) * 256 + d;
  7. }
  8. mat read_mnist_image(const string fileName)
  9. {
  10. fstream File;
  11. mat image;
  12. File.open(fileName);
  13. if (!File.is_open()) // cannot open file
  14. {
  15. cout << "文件打不开啊" << endl;
  16. return mat(0, 0, fill::zeros);
  17. }
  18. uchar a, b, c, d;
  19. File >> a >> b >> c >> d;
  20. int magic = reverseInt(a, b, c, d);
  21. if (magic != 2051) //magic number wrong
  22. {
  23. cout << magic;
  24. return mat(0, 0, fill::zeros);
  25. }
  26. File >> a >> b >> c >> d;
  27. int num_img = reverseInt(a, b, c, d);
  28. File >> a >> b >> c >> d;
  29. int num_row = reverseInt(a, b, c, d);
  30. File >> a >> b >> c >> d;
  31. int num_col = reverseInt(a, b, c, d);
  32. // 文件头读取完毕
  33. image = mat(num_img, num_col * num_row, fill::zeros);
  34. for(int i = 0; i < num_img; i++)
  35. for (int j = 0; j < num_col * num_row; j++)
  36. {
  37. File >> a;
  38. image(i, j) = double(a);
  39. }
  40. return image;
  41. }
  42. mat read_mnist_label(const string fileName)
  43. {
  44. fstream File;
  45. mat label;
  46. File.open(fileName);
  47. if (!File.is_open()) // cannot open file
  48. {
  49. cout << "文件打不开啊" << endl;
  50. return mat(0, 0, fill::zeros);
  51. }
  52. uchar a, b, c, d;
  53. File >> a >> b >> c >> d;
  54. int magic = reverseInt(a, b, c, d);
  55. if (magic != 2051) //magic number wrong
  56. {
  57. cout << magic;
  58. return mat(0, 0, fill::zeros);
  59. }
  60. File >> a >> b >> c >> d;
  61. int num_lab = reverseInt(a, b, c, d);
  62. // 文件头读取完毕
  63. label = mat(num_lab, 10, fill::zeros);
  64. for (int i = 0; i < num_lab; i++)
  65. {
  66. File >> a;
  67. label(i, int(a)) = 1;
  68. }
  69. return label;
  70. }

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. 【Azure API 管理】从微信小程序访问APIM出现200的空响应的问题中发现CORS的属性[terminate-unmatched-request]功能

    问题描述 使用微信小程序调用APIM(API Management)中的接口,发现POST和PUT请求被拦截,返回的状态码为200,但是无消息内容. 在小程序中的调用JS代码如: 通过浏览器测试得到的 ...

  2. 漫漫Java路1—基础知识2—注释和命名规则

    ## 注释 1. 单行注释 ```java //这是一个注释 ``` 2. 多行注释 ```java /* 这是一个注释 */ ``` 3. 文档注释 ```java /** * * * */ ``` ...

  3. Java方法:命令行传参,重载,可变参数,递归

    Java方法:System.out.println()//系统类.out对象.输出方法Java方法是语句的集合,他们在一起执行一个功能方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中 ...

  4. C# 通过ServiceStack 操作Redis——Set类型的使用及示例

    ServiceStack 程序集里面没有方法注解,我在这里将注解添加上去,有不当之处,欢迎指正 Console.WriteLine("---Set类型---"); //添加 set ...

  5. webpack4.x 从零开始配置vue 项目(二)基础搭建loader 配置 css、scss

    序 上一篇已经把基本架子搭起来了,现在来增加css.scss.自动生成html.css 提取等方面的打包.webpack 默认只能处理js模块,所以其他文件类型需要做下转换,而loader 恰恰是做这 ...

  6. 世界国省市区SQL语句(mysql)

    CREATE TABLE loctionall ( country VARCHAR(40) , provice VARCHAR(40) , city VARCHAR(40) , CONSTRAINT ...

  7. 攻防世界 reverse xx

    xx 程序开始验证输入长度为19位. 取前4位(作为后面加密的key),验证这4位都在'qwertyuiopasdfghjklzxcvbnm1234567890'中. 将key用0填充为16位 调用x ...

  8. 攻防世界 reverse 进阶 easyre-153

    easyre-153 查壳: upx壳 脱壳: 1 int __cdecl main(int argc, const char **argv, const char **envp) 2 { 3 int ...

  9. 设计模式—singleton(单例模式)

    单例模式 单例设计模式属于创建型模式,它提供了一种创建对象的最佳方式.这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建. 这个类提供了一种访问其唯一的对象的方式,可以直接 ...

  10. Java例题_19 打印菱形图案

    1 /*19 [程序 19 打印菱形图案] 2 题目:打印出如下图案(菱形) 3 * 4 *** 5 ***** 6 ******* 7 ***** 8 *** 9 * 10 */ 11 12 /*分 ...