python中要识别图像信息用于机器学习等的话,使用opencv和numpy就可以了,简单快捷。
目录
以一张随手创建的简单图片为例:
它的二进制形式(开头部分)如下:
当然,这其实是十六进制。二进制指的是计算机中按二进制数进行存储,为了便于查看显示为十六进制而已。
如何查看二进制形式:
把文件的后缀名去掉,然后用Sublime或UltraEdit等打开即可。注意如果用记事本或notepad++等打开的话可能会乱码。
分块
JPEG文件内部分为若干块,这些块由ff开头(截图中已标出部分),ff后紧跟的一个标记符指明了这个块的类型。
这些分块按出现顺序分别是:
SOI | ff d8 | 文件开始 |
APP0 | ff e0 | 定义交换格式和图像识别信息 |
DQT | ff db | 定义量化表 |
SOF0 | ff c0 | 帧开始 |
DHT | ff c4 | 霍夫曼(Huffman)表 |
SOS | ff da | 扫描行开始 |
EOI | ff d9 | 文件结束 |
首先是两个比较简单和特殊的块:
FFD8、FFD9-SOI、EOI-文件开始与结束
名称 | 二进制数 | 含义 |
SOI | ff d8 | 文件开始 |
EOI | ff d9 | 文件结束 |
需要注意截图中Sublime自动按两个字节一组显示的,但实际上ff并不一定只出现在第单数个字节处,有可能ff和标记符间隔着一个空格。
(也就是说你按[标记符+空格]进行搜索,不一定能找到全部的分块)
FFE0-APP0-图像识别信息
0010指该块长度为16个字节(不包括ffe0)
4a46 4946 00是JFIF格式标识码
01 01是版本号(第一个01是主版本号,第二个01是次版本号)
01是单位(00=无单位;01=点数/英寸;02=点数/厘米)
0078为水平分辨率
0078为竖直分辨率
00为水平点数
00为竖直点数
FFDB-DQT-定义量化表
一共有两个DQT块,它们ffdb后面都紧跟着一个0043,意味着这两个DQT块的长度(不包括ffdb)都为67个字节。
DQT块定义了图像的量化表,参与到图像的压缩中,我没有用到这一部分,暂时不讲(以后用到了再补)
FFC0-SOF0-图像基本信息
同样的,0011指示了SOF0块长度为17个字节。
前8个字节分别为:
字节数 | 示例中的值 | 示例中的含义 |
2 | 0011 | SOF0块长度为17个字节 |
1 | 08 | 每个像素的每个颜色分量为8位 |
2 | 02 0d | 图片高度为525(直接换算成十进制) |
2 | 02 5a | 图片宽度602(直接换算成十进制) |
1 | 03 | 组件数量为3 |
JPEG一般采用yCrCb格式,因此最后的组件数量通常为3(每个组件就是像素的一个颜色分量)
y指的是亮度;Cr指的是红色分量;Cb指的是蓝色分量。
每个组件包含三个字节:
1 | 01 | 02 | 03 | 01=Y;02=Cb;03=Cr;04=I;05=Q |
1 | 22 | 11 | 11 | 0~3位=竖直采样系数;4~7位=水平采样系数 |
1 | 00 | 01 | 01 | 量化表号 |
第一个字节指示这个组件是什么,除了之前说的y、Cr、Cb以外,还有I和Q。
I和Q是YIQ色彩空间中使用的,y是亮度,I代表In-phase,色彩从橙色到青色,Q代表Quadrature-phase,色彩从紫色到黄绿。
FFC4-DHT-定义Huffman表
示例中共有4张Huffman表,分别为亮度AC(交流)、亮度DC(直流)、色度AC、色度DC。
(暂时没弄太明白,之后补充)
FFDA-SOS-扫描行开始
紧跟着ffda的000c描述段长度,值为6+[组件数量],这里组件数量为3。
之后的03表示组件数量为3,这里的值必须在1到4之间。
01表示组件号码为1(y),00的0-3位:AC表号 (值=0~3),4-7位:DC表号(值=0~3)
在SOS后记录的就是图像数据,从左到右从上到下依次排列。(是经过压缩算法处理过后的)