1. 为什么这么多年了,我们还在跟JPG/JPEG打交道
做数字图像处理的同学,几乎绕不开这个话题:一张照片从相机里出来,不管是手机拍的还是单反拍的,默认格式基本都是JPEG(文件后缀通常是.jpg)。哪怕你用了RAW格式,想发朋友圈、传网页、做数据集预处理,最后还是得转成JPG。微信聊天记录里那些打不开的图片缓存文件,说到本质,也多半是丢了文件头的JPEG数据。
JPEG之所以能统治图像存储几十年,核心原因就一句话:它在“画质”和“体积”之间找到了一个绝大多数场景都能接受的平衡点。一个10MB的BMP位图,转成JPG可能只有几百KB,肉眼看起来差别不大。这个压缩能力,让它在互联网早期带宽稀缺的年代站稳了脚跟,也让它成为数字图像处理入门绕不开的第一个真实案例。
这篇文章我就结合实际踩坑经验,把JPEG的核心原理、格式结构、处理流程、常见问题一次讲清楚。适合正在学数字图像处理的学生、刚入门图像算法开发的工程师,还有那些遇到“文件打不开”“后缀改一下就完事了吗”这类困惑的普通用户。全文不堆公式,但该严肃的地方一个都不会少。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JPEG的压缩思想:它不是简单“删像素”,而是骗过你的眼睛
很多初学者有个误解,觉得JPG压缩就是隔几个像素抽掉一个,分辨率变低了所以文件变小。这是完全错误的。JPEG是有损压缩,但它损失的主要是人眼不敏感的高频细节,而不是简单粗暴地丢像素。
2.1 压缩前的第一步:把RGB换成YCbCr
JPEG压缩的第一步,是把图像从RGB颜色空间转换到YCbCr颜色空间。Y代表亮度(luma),Cb和Cr代表蓝色色度和红色色度。为什么要做这一步转换?因为人眼对亮度的细小变化非常敏感,但对颜色的变化相对迟钝。
打个比方:你看一部电影,如果画面变暗或变亮了一点,你会立刻注意到。但如果画面里某个物体的红色饱和度稍微差了那么一点点,你基本察觉不到。JPEG就是抓住了这个生理特性,把亮度信息和颜色信息拆开,然后区别对待。
实际操作中有一个关键参数叫色度抽样,常见的4:2:0抽样就是指两个像素横向、两个像素纵向组成一个2x2块,这个块共享一组Cb、Cr值,而每个像素都有自己的Y值。这样色度信息直接减少到原来的四分之一,而人眼几乎无感知。
这也是为什么你在Photoshop里保存JPG时,有时候会看到“4:2:0”“4:4:4”之类的选项。4:4:4表示不抽样,文件大;4:2:0是默认值,文件小。如果是做图像处理算法,需要尽量保留颜色信息,我建议选4:4:4,否则后续做颜色相关的计算会吃亏。
2.2 DCT变换:把像素搬进频率世界
转换完颜色空间之后,图像被切成一个个8x8的小块(实际编码单元)。接下来的关键是离散余弦变换(DCT)。
DCT的作用是把一个8x8的像素块,变成一组频率系数。你可以这样理解:一个复杂的像素图案,可以被拆成若干不同频率、不同幅度的“基础图案”叠加。低频部分描述大面积的明暗变化,高频部分描述边缘、纹理等细节。
人眼对高频细节的敏感度低。所以JPEG在做DCT之后,就拿到了一个机会:对高频系数进行更粗的量化,让很多高频系数变成0,这样后面对0值进行编码时,就可以用很短的码来表示。压缩空间就这么腾出来了。
这一步是整个JPEG压缩中信息损失最大的环节,而且损失是不可逆的。你保存一次JPG,就会丢一次高频信息。如果你反复编辑、反复保存,每次都会重新做DCT和量化,高频信息层层丢失,最终出现明显的块状模糊,这就是“马赛克”的来源。
2.3 量化表:压缩率的核心控制旋钮
量化是JPEG压缩里的质量控制关卡。量化器内部有一张8x8的量化表,表中每个位置对应DCT系数矩阵中的频率位置。高频位置的量化步长通常更大,所以系数被除得更多,丢得更狠。
JPEG标准提供了亮度和色度两张默认的量化表,但编码器可以根据质量参数(quality factor,常说的q值)缩放量化表。q值越高,量化步长越小,保留的细节越多,文件越大;q值越低,量化步长越大,细节丢得多,文件越小。
我在实际处理中习惯用q=85到q=92之间的质量来保存中间结果。低于75的时候,放大图片能看到明显的振铃效应和色块,这在做图像算法评估时是不可接受的。特别提醒:如果你在做目标检测或者图像分割的数据集,训练集和测试集不要混用不同质量参数的JP
