返回首页

JPEG 与视觉神经生理学:该格式如何欺骗眼睛

本文解释了 JPEG 格式如何基于人类视觉的神经生理特征:杆细胞和锥细胞的比例、外周色觉、V1 神经元活动和对比敏感度 (CSF)。提供了 YCbCr、chroma subsampling 4:2:0、DCT 和量化的技术细节及代码示例。

JPEG 如何模拟你的视觉:技术剖析
Advertisement 728x90

JPEG如何欺骗视觉系统:根植于神经生理学的工程设计

JPEG不仅仅是一种压缩格式。它是一个基于人类视觉的三维模型,早在1992年就被编码进算法中。它并非单纯优化数据存储,而是模拟人眼所见、大脑如何处理这些信息,以及视觉系统在哪些环节会丢失信息。结果就是:文件大小缩小了5到10倍,而感知上却几乎毫无损失。这种效果并不是通过简化数学计算实现的,而是精准匹配了生物约束——视网膜感光细胞密度、对比敏感度以及大脑皮层的空间频率选择性。以下将从视觉神经生理学的角度,对JPEG流程中的每个阶段进行技术解析。

YCbCr:按生物学意义分离信号

JPEG编码的第一步是将RGB转换为YCbCr。这并非出于技术便利,而是直接体现了视网膜的解剖结构。人类约有1.2亿个视杆细胞(对亮度敏感),而视锥细胞仅有600万至700万个(负责色彩感知),比例约为20:1。因此,视觉系统对亮度渐变的分辨能力远高于对色彩细微差别的分辨能力。

计算Y通道的公式是:

Google AdInline article slot
Y = 0.299 × R + 0.587 × G + 0.114 × B

这些系数并非随意设定:其中绿色的0.587反映了人眼在约555纳米处的峰值敏感度——即光谱中的黄绿区域,这一波长恰好适应了进化过程中在绿叶间寻找成熟果实的需求。这就是为什么使用这些权重的黑白图像看起来更加立体、对比强烈,而如果采用均匀平均(0.33R + 0.33G + 0.33B)则会显得平淡、像“肥皂水”一样。

在YCbCr模式下,Y通道包含了所有对感知至关重要的信息——结构、轮廓和纹理。Cb和Cr只是用于调整色彩色调的分量,可以被大幅处理而不影响感知质量。

色度抽样:根据周边视觉解剖结构压缩色彩

转换完成后,便进入色度抽样阶段——降低色彩通道的分辨率。最常见的4:2:0模式意味着每四个Y像素块对应一个Cb块和一个Cr块(2×2像素)。实际上,75%的色彩信息都被舍弃了。

Google AdInline article slot

这与视网膜解剖结构完全吻合:视锥细胞集中在中央凹,而越往周边密度越低。平均而言,色彩视觉的空间分辨率比单色视觉低四倍。JPEG并不是“丢掉”色彩,而是保留了视觉系统在图像每个局部区域所能分辨的精确色彩信息。

为了验证这一点,只需在Photoshop中打开任意一张JPEG,将其拆分为YCbCr三个通道,然后比较Y与Cb/Cr的视觉质量:后两者会显得模糊、低频——但当叠加到Y通道上时,大脑会自动恢复图像的完整性。这并非格式本身的缺陷,而是充分利用了视觉皮层的工作方式。

DCT与量化:盲点的频率映射

离散余弦变换(DCT)将图像分割成8×8的区块,并把每个区块分解为64个基底成分——从低频渐变到高频边缘、噪声和纹理。这并非抽象概念:初级视觉皮层(V1)中的神经元会对特定空间频率的定向条纹作出反应,实际上就是在进行DCT的生物学近似。

Google AdInline article slot

接下来,这些系数会经过量化——除以量化表中的数值并四舍五入。标准的Y通道量化表具有如下结构:左上角的除数最小(低频、高敏感度),右下角的除数最大(高频、低敏感度)。这张表并非工程师的猜测,而是基于人类心理视觉实验得出的对比敏感度(CSF)经验地图。CSF的峰值出现在每度视角3到5个周期;超过约60个周期/度,人类就无法再分辨细节了。

当你在Photoshop中将质量设为80时,其实是在设定一个阈值,只有低于这个阈值的频率才会受到量化的影响。而当质量降到5时,算法甚至开始清零中频——那些大脑用来识别形状和纹理的关键频率。因此,感知质量会急剧下降。

实验:可视化眼睛看不见的部分

要确切了解JPEG认为哪些部分“不可见”,可以做一个简单的实验:用不同质量保存同一张图片为JPEG,然后计算原始PNG与压缩版之间的差异。

from PIL import Image
import numpy as np

original = np.array(Image.open("photo.png")).astype(np.float32)

for q in [95, 80, 50, 20, 5]:
    Image.open("photo.png").save(f"q{q}.jpg", quality=q)
    compressed = np.array(Image.open(f"q{q}.jpg")).astype(np.float32)

    diff = original - compressed
    diff_visual = ((diff - diff.min()) / (diff.max() - diff.min()) * 255)
    Image.fromarray(diff_visual.astype(np.uint8)).save(f"diff_q{q}.png")

结果令人震惊:

  • 在质量95时,差异图几乎全黑——损失仅限于噪声。
  • 在质量80时,差异主要集中在轮廓、细线和高频纹理(如头发、织物)上——恰恰是DCT分配到高频系数、且被量化最先清零的部分。
  • 在质量5时,差异图已经能明显看出是“原图的颗粒版”——算法早已突破了CSF的界限,开始移除对感知形状至关重要的信息。

这并非代码上的偶然现象,而是你自身视觉阈值的真实映射。

质量80:CSF曲线上的拐点

为什么偏偏是80——这个事实上的网络标准?绘制文件大小与SSIM(结构相似性指数)随质量变化的曲线可以看到,在80左右出现了一个明显的拐点。在此之前,提高质量(SSIM)的同时文件大小只小幅增加;之后,文件大小翻倍,而SSIM提升却微乎其微(不到0.001)。

这正好对应着从“剔除不可见频率”到“剔除可见频率”的转变。质量低于80时,量化操作处于CSF接近零的区域;而质量高于80时,则进入了CSF急剧上升的区域。因此,“质量80”并非什么神奇数字,而是针对典型图像在标准观看条件下(30厘米距离、1080p分辨率)的对比敏感度阈值的实际近似。

重要启示

  • JPEG并非压缩“画面”,而是模拟了视觉系统的运作方式:视杆/视锥→Y/CbCr,周边色彩视觉→色度抽样,V1中的神经频率选择性→DCT,对比敏感度阈值→量化表。
  • 公式Y = 0.299R + 0.587G + 0.114B中的系数并非近似——它们是对人眼光谱敏感度的参数化建模。
  • 4:2:0的色度抽样模式符合单色与彩色视觉的实际分辨率比例(约4:1),而非技术硬件限制。
  • 量化表并非静态模板,而是基于实验室活体实验得出的CSF经验地图。
  • 质量80并非“妥协”,而是算法停止在不可见损失区域工作、开始影响图像中可感知成分的临界点。

— Editorial Team

Advertisement 728x90

继续阅读