处理一批灰度图,深部信号弱、看不清,就加了道增益(gain)把深部的幅值往上提。调完增益打开图一看,奇怪了——本来是想让深部亮起来,结果观感是浅部反而变灰了,深部也没见亮多少。第一反应是增益写错了,查了半天代码没问题。

后来才反应过来,这不是增益的 bug,是显示的色阶在捣乱。

全局百分位定色阶,会被放大后的极值撑大

显示这种动态范围很大的灰度数据,一般不会直接用最小最大值定 vmin/vmax——少数极大值(比如直达波那种)会把范围撑得太大,绝大多数数据挤在一头,图就「非黑即白」。常见的做法是用百分位,比如取第 1 和第 99 百分位作为显示的上下限,把长尾削掉,层次就出来了。

问题在于,这个百分位是整张图算的。增益一上去,深部那些本来不强、但被放大了的反射,幅值被抬得很高,整张图的 p99 跟着水涨船高(实测能从不到一万飙到二十多万)。色阶的上限一拉高,那些没被增益放大的浅部数据,在新的色阶里就全被挤向中灰了。

所以调大增益参数,看到的不是「深部变亮」,而是「浅部变灰」——因为色阶被深部的极值撑宽了,浅部在更宽的尺度里自然显得更暗。本质是灰度级被重新分配了,不是数据本身变暗。

想看增益的真实效果,得把色阶锁住

要判断增益到底有没有把深部提亮,得让前后两幅图用同一把尺子量。具体就是把「加增益前」那张图的百分位 [1,99] 记下来,加增益后显示的时候还用这同一组 vmin/vmax,不让它重新算:

vmin, vmax = np.percentile(raw, [1, 99])   # 用原始图定一次色阶

ax[0].imshow(raw, vmin=vmin, vmax=vmax, cmap='gray') # 原图
ax[1].imshow(gained, vmin=vmin, vmax=vmax, cmap='gray') # 增益后,共用同一色阶

这样色阶锁死了,增益放大的深部目标是真的「冒出来」变亮,浅部因为没动还是原来的灰度,对比一目了然。配套加个「锁定色阶」的开关,勾上两图共用原始百分位,不勾就各自算各自的——平时看绝对层次用各自的,调增益判效果一定得锁。

这事给我的一个教训:调一个看起来「没生效」的处理参数,先别急着怀疑算法,想想显示环节是不是也跟着动了。增益改的是数据,百分位色阶也跟着数据重新算,两者一叠加,呈现出来的变化就不是单纯增益的效果了。判断一个处理到底有没有用,得把它放在固定的显示基准下看,不然你调的是参数,被糊弄的其实是色阶。