12

编程小知识之 Dithering

 3 years ago
source link: https://blog.csdn.net/tkokof1/article/details/103316918
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

编程小知识之 Dithering

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

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

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

在这里插入图片描述

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

但是如果显示器能够显示的颜色数量有限(譬如只能显示 216 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 7/16,1/16,5/16,3/16 的比例添加到其 右, 右下, 下, 左下 的像素上去, wiki 上已经给出了相关伪码,这里也有一份完整的代码实现(基于 Unity),有兴趣的朋友可以仔细看看~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK