编程小知识之 Dithering

本文简单介绍了 Dithering(抖动) 的一些知识

图形后处理有一种操作称为 Dithering(抖动),所谓 Dithering,就是一种能够在较小色彩空间上"模拟出"较大色彩空间的图像处理方法,说的有些抽象,我们来举个例子:

假设我们需要在显示器上显示以下图片(图片来自这里):

在这里插入图片描述

图片的像素格式为 R G B 24 RGB24 (像素的 R , G , B R,G,B 通道各占 1 1 个字节( 8 8 位),一个像素占用 3 3 个字节(共 24 24 位)), R G B 24 RGB24 格式的像素总共能够表达 2 24 = 16777216 2^{24} = 16777216 种不同的颜色,现在的大部分显示器也能够显示这么多种颜色(这里我们暂时忽略伽马校正等因素的影响),所以我们不用对图片做什么特殊处理,直接输出显示即可~

但是如果显示器能够显示的颜色数量有限(譬如只能显示 216 216 种颜色),那么就需要对原图片进行处理了,一种简单的方法就是对图片像素进行截断或者舍入处理,但是这样会让图片产生明显的色带(color banding)现象,譬如上面所示的图片,经过(像素)截断(舍入)之后,大概会显示成这个样子(图片来自这里):

在这里插入图片描述

可以看到显示效果很差,那有没有办法改善呢?答案就是使用 Dithering(抖动): Dithering(抖动) 通过调整一个像素周围像素的颜色值,使人眼产生错觉,从而"模拟出"更多的显示颜色(譬如将黑白两种颜色并列在一起就可以"模拟出"灰色(人眼错觉的关系)),仍然拿上面的图片举例,经过 Dithering(抖动) 之后,显示效果会变成这样(图片来自这里):

在这里插入图片描述

可以看到显示效果较之前的版本要好了不少(虽然两者的颜色空间(使用到的颜色数量)其实是相同的)

那具体 Dithering(抖动) 是怎么调整图片像素的呢?方法其实有不少,这里我们简单介绍一下经典的 Floyd–Steinberg 算法,算法的基本思想就是使用误差扩散(error diffusion),所谓误差扩散,简单来说,就是将像素截断或者舍入之后的颜色误差扩散(添加)到周围的像素颜色上去, Floyd–Steinberg 算法采用的误差扩散方式如下所示(图片来自wiki):

在这里插入图片描述

图中的 * 号代表的就是当前正在处理(抖动)的像素,该像素截断或者舍入之后的颜色误差会按 7 / 16 , 1 / 16 , 5 / 16 , 3 / 16 7/16, 1/16, 5/16, 3/16 的比例添加到其 右, 右下, 下, 左下 的像素上去, wiki 上已经给出了相关伪码,这里也有一份完整的代码实现(基于 Unity),有兴趣的朋友可以仔细看看~

参考资料

发布了142 篇原创文章 · 获赞 146 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/tkokof1/article/details/103316918
今日推荐