scratch lenet(1): 读写 pgm 图像文件
scratch lenet(1): 读写 pgm 图像文件
文章目录
- scratch lenet(1): 读写 pgm 图像文件
- 1. 目的
- 2. pgm 格式介绍
- 2.1 概要
- 2.2 meta 信息
- 2.3 像素内容
- 3. 创建 .pgm 文件
- 4. 使用C语言读取 .pgm 灰度图文件
- 4.1 实现
- 4.2 解释
- 5. 使用C语言保存 .pgm 灰度图文件
1. 目的
最近在 github 上关注了 LLM 的流行库 llama.cpp 和 whisper.cpp 的作者 Georgi Gerganov, 简称 gg 哥。 通过 gg哥关注到了 deepdream 算法作者开源的 deepdream_c 代码。完全用 C89 写成的 deepdream, 编译只需要1秒钟, Windows 和 Linux 都能运行。完全不依赖 PyTorch 和 OpenCV 等框架, 连 C++ 都没使用,非常克制, 可移植性非常高。这个风格和 gg 哥的风格有点像的: 喜欢单一的 .vimrc
文件, 写 ggml 主要放在一个16000行的文件中。打算按照这种风格, 用 C99 标准,不借助外部库, 实现 lenet。
实现过程中难免遇到不熟悉的内容, 因为这是一种“全都自己造”的风格; 没关系, 我会尝试逐一弄懂, 以博客形式分享出来。
这是这系列的第一篇, 分享的是 pgm 图像的读写。用 pgm 格式的原因是, 项目规模非常小的时候, BMP 的编解码都显得过于复杂, 目前只需要灰度图的前提下, pgm 足够使用, 而 Linux KDE 下的默认图像查看器, 完全可以查看 pgm 格式。
2. pgm 格式介绍
2.1 概要
pgm 里的 g 表示 gray, 是灰度图, 数据范围通常是 0 到 255。
pgm 文件,以二进制格式进行存储, 不过它的内容其实是 文本 + 二进制混合的:meta 信息是文本, 图像像素内容是二进制。
2.2 meta 信息
第一行是 P5 两个字符。
第二行是空格分隔的两个整数, 分别表示图像宽度,高度。
第三行是一个整数, 表示像素最大取值, 通常是255。
这些信息都是文本格式写入, 也就是用 fprintf 写入, fscanf 读取。也可以用记事本查看 .pgm 文件。
2.3 像素内容
用二进制形式存储, row-major。
也就是说, 用 fread 读取, 用 fwrite 写入。
3. 创建 .pgm 文件
我的开发环境是 Ubuntu 22.04, KDE 桌面, 也可以叫做 “KUbuntu”. 不过我认为 KUbuntu 的叫法很奇怪,Ubuntu 并不限制你用什么桌面, 安装了 KDE 之后也可以安装 Cinamon, XFCE 等桌面, 如果安装的不是 Ubuntu 而是 OpenSude, Manjaro 等 Linux 发行版, 也可以安装 KDE。
我使用 KDE 里的 KolourPaint 这个绘图软件,制作一张手写数字“3”的图像:
保存图像, 选择 .pgm 格式:
4. 使用C语言读取 .pgm 灰度图文件
4.1 实现
简单起见, 我们直接读取刚刚用 KolourPaint 生成的 3.pgm 文件。你也可以直接下载:
3.pgm:一张绘图图,格式为pgm
uchar g_image[784];
void read_pgm_image()
{FILE* fin = fopen("3.pgm", "rb");char magic[3];int width, height;int nscan = fscanf(fin, "%2s\n%d %d\n255\n", magic, &width, &height);if (nscan == 3 && magic[0] == 'P' && magic[1] == '5'){fread(g_image, 784, 1, fin);}fclose(fin);
}
如果打算读取其他 .pgm 文件, 可以自行重构, 其中 784 等于 28 * 28
, 是图像大小。
4.2 解释
FILE* fin = fopen("3.pgm", "rb");
是以二进制格式打开文件 3.pgm.
读取第一行的 P5
两个字符时, 使用了
char magic[3];
而不是
char magic[2];
原因是避免内存越界, 具体分析见 Cracking C++(13): 读取不超过n个字符。
int nscan = fscanf(fin, "%2s\n%d %d\n255\n", magic, &width, &height);
是读取 meta 信息,是以文本方式读取。
fread(g_image, 784, 1, fin);
是读取像素内容, 是按二进制格式读取。
5. 使用C语言保存 .pgm 灰度图文件
和读取过程是配套的,代码如下
void write_pgm_image(uchar* image, int width, int height, const char* filename)
{FILE* fout = fopen(filename, "wb");fprintf(fout, "P5\n%d %d\n255\n", width, height);fwrite(image, width * height, 1, fout);fclose(fout);
}
scratch lenet(1): 读写 pgm 图像文件相关推荐
- scratch lenet(9): C语言实现tanh的计算
文章目录 1. 目的 2. tanh ( x ) \tanh(x) tanh(x) 的 naive 实现 2.1 数学公式 2.2 naive 实现 3. tanh ( x ) \tanh(x ...
- scratch lenet(4): 开根号的C语言实现
文章目录 1. 目的 2 二分法求开根号 2.1 数学原理:单调函数 2.2 代码实现:注意事项 2.3 代码实现: 完整代码 2.4 验证结果 3. 牛顿法 3.1 数学原理:迭代求解 3.2 代码 ...
- C++读写BMP图像文件
bmp格式图像分为四个部分: 1.位图文件头(Bitmap File Header) ,大小:14字节 主要包括位图文件大小和位图文件类型信息. 2.位图信息头(Bitmap Info Header) ...
- java import imageio_java数字图像处理基础使用imageio写图像文件示例
一个BufferedImage的像素数据储存在Raster中,ColorModel里面储存颜色空间,类型等信息,当前Java只支持一下三种图像格式- JPG,PNG,GIF,如何向让Java支持其它格 ...
- Java数字图像处理基础知识 - 必读
转载自:http://blog.csdn.net/jia20003/article/details/7279667 写了很多篇关于图像处理的文章,没有一篇介绍Java 2D的图像处理API,文章讨论和 ...
- 完全手册-MATLAB使用详解:基础、开发及工程应用
[书名]完全手册-MATLAB使用详解:基础.开发及工程应用 [作者]董霖 编著 [ISBN]978-7-121-07397-7 [出版社]电子工业出版社 [出版日期]2009年1月 [内容简介] M ...
- OpenCV读写图像文件解析
OpenCV读写图像文件解析 imdecode 从内存中的缓冲区读取图像. C++: Mat imdecode(InputArray buf, int flags) C++: Mat imdecode ...
- pbmplus-图像文件格式转换包与PBM/PGM/PPM 格式图像文件
pbmplus-图像文件格式转换包 PBMPLUS 是一个用于多种图像类型和可移植格式(portble formats)之间来回转换的工具包.官方网站主页介绍,和下载地址在这里.该工具的想法是如果你想 ...
- 图像文件的读写和转换——BMP转YUV
文章目录 数据压缩实验(二) 一.BMP文件格式分析 二.YUV文件格式分析 1.概述 2.YUV采样 Planar平面格式 RGB转YUV 三.实验过程 1.实验思路 2.实验代码 四.实验结果 数 ...
最新文章
- 【css】如何实现响应式布局
- Redis操作Set类型
- AngularJS+Jersey下载excel
- 使用 PSD Validator 在线校验 PSD 文件的质量
- 华为P30/P30 Pro细节再曝光:3.5mm耳机插孔和红外遥控各占其一
- react 轮播组件
- linux处理除零异常,linux – 如何在x86程序集中使用中断来触发被零除错误异常?...
- 腾讯想拿到Big Data资源,8h删抓紧时间!!
- matlab练习程序(倾斜校正,透视变换)
- 数据库事务的特性(ACID)
- c语言三位数倒序,C语言求助!一个三位数的逆序数,总是编不对
- hdu 5745 la vie en rose
- 2021 年 15 款适用于 PC 和 Mac 的最佳 Android 模拟器
- android网络诊断服务(ping网络的实现,判断网络是否可用)
- 当前 .NET SDK 不支持将 .NET Core 2.2 设置为目标。请将 .NET Core 2.1 或更低版本设置。
- IWAM账号密码不一致引起IIS无法处理ASP文件
- 基于Java--获取城市天气与给手机发送验证码--HTTP协议实践
- 数据分析师成长路径-第二阶段
- 华为鸿蒙电视配置,华为旗下荣耀智慧屏PRO55英寸AI摄像头鸿蒙系统4K超清电视机...
- Python 简易版小工具 | 计算天数
热门文章
- MySQL-比较两个表不同的数据
- 获晨晖资本领投的1.5亿元A轮融资,犀思云想为企业用户提供NAAS服务
- 支撑腾讯直播百亿请求的 Redis 集群是如何工作的
- 考研英语 - word-list-42
- 【机器学习】Reinforcement Learning-强化学习学习笔记
- 2 监督学习与非监督学习
- ROS---进行建图或者move_base路径规划时出现打滑现象(雷达匹配不上地图)的解决方法 附gmapping建图配置参数
- HTTP请求流程(超级详细)
- 银行票据业务如何实现BI赋能
- 用户即将一分钟后关闭计算机,win10即将注销您的登陆怎么办_win10将在一分钟后注销的解决方法...