PAYATHON 2026

Processing 中 Bayer dithering 为什么会覆盖白色边缘像素?

数据小陈

结论

白色边缘像素会被 dithering 覆盖,主要是因为跳过像素的判断比较了含义不同的值:pValue 是 red(iValue) 返回的红色通道值,白色时为 255;white 则是 Processing 的 color 值。因此,pValue != white 无法正确识别白色像素,dithering 循环仍会处理并改写它们。

还有一个独立问题:生成阈值时,newK / 63 使用整数除法。除 63 外的值都会先变成 0,再乘以 255,导致阈值矩阵几乎只有 0 和 255,无法将 Bayer 值均匀映射到 0–255。

修正跳过白色像素的判断

当前代码片段是:

color iValue = img.get(xx, yy);
float pValue = red(iValue);
if (pValue != white) {
    // dithering
}

pValue 是通道值,white 是颜色值。直接比较像素颜色即可:

color iValue = img.get(xx, yy);
if (iValue != white) {
    float pValue = red(iValue);
    // dithering
}

这样,白色边缘像素就会跳过后续 dithering。如果只想根据红色通道判断亮度,也可以比较 red(iValue) != 255。不过,红色通道为 255 的其他颜色也会被当成白色。当前代码将边缘设为纯白,因此比较完整颜色更符合预期。

修正阈值缩放

将 setup() 中的整数除法:

int newS = (newK / 63) * 255;

改成先乘再除:

int newS = newK * 255 / 63;

newK 的范围是 0–63,这种写法会将它映射到 0–255。结果仍会向下取整,这是预期的。

检查像素处理顺序

代码先用 img.set(x, y, white) 标记边缘,再进入 dithering 循环读取 img。只要跳过条件正确,白色像素就能保留下来。把边缘处理移到循环末尾,本身无法修正原来的比较条件。

如果之后 dithering 的计算需要读取相邻像素,建议从一张输入图读取,并将结果写入另一张输出图,以免先前写入的结果影响后续计算。当前 Bayer 判断对每个像素独立处理,可以先修正白色判断来验证问题。

此外,image(img, 0, 0) 在 draw() 开头绘制的是处理前的图像,最终结果则在末尾再次绘制。如果不需要先显示原图,可以移除开头的绘制,减少绘制步骤。

备注:内容仅供参考。