TL; DR:由于夹持,在0和1的边缘情况下2 * 1LSB三角pdf抖动中断。一种解决方案是在这些边缘情况下使用1位均匀抖动。
我要添加第二个答案,因为发现结果比我原先认为的要复杂一些。看来这个问题是“待办事项:需要限制?” 在我的代码中,因为我在2012年从规范化切换到三角抖动...。终于可以看一下了:)整个帖子中使用的解决方案/图像的完整代码:https : //www.shadertoy.com/view/llXfzS
首先,当我们使用2 * 1LSB三角pdf抖动将信号量化为3位时,这就是我们要研究的问题:
-本质上是hotmultimedia展示的内容。
随着对比度的增加,问题中描述的效果变得显而易见:在边缘情况下,输出结果不会平均为黑/白(实际上,在这样做之前,其输出范围远远超过了0/1)。
查看图表可提供更多的见解:
(灰色线标记为0/1,灰色也是我们试图输出的信号,黄线是抖动/量化输出的平均值,红色是误差(信号平均值))。
有趣的是,平均输出不仅在极限处不是0/1,而且不是线性的(可能是由于噪声的三角形pdf)。观察下端,可以直观地看出输出为何会发散:当抖动信号开始包含负值时,钳位输出会更改输出的较低抖动部分的值(即负值),从而增加平均值。图示似乎井然有序(均匀,对称的2LSB抖动,平均值仍为黄色):
现在,如果仅使用1LSB归一化的抖动,则边缘情况完全没有问题,但是当然,我们失去了三角形抖动的良好特性(请参见本演示文稿)。
一个(实用的,经验的)解决方案(hack)将恢复为[-0.5; 0.5 [边缘抖动的均匀抖动:
float dithertri = (rnd.x + rnd.y - 1.0); //note: symmetric, triangular dither, [-1;1[
float dithernorm = rnd.x - 0.5; //note: symmetric, uniform dither [-0.5;0.5[
float sizt_lo = clamp( v/(0.5/7.0), 0.0, 1.0 );
float sizt_hi = 1.0 - clamp( (v-6.5/7.0)/(1.0-6.5/7.0), 0.0, 1.0 );
dither = lerp( dithernorm, dithertri, min(sizt_lo, sizt_hi) );
它在固定边沿的同时,在剩余范围内保持三角抖动不变:
因此,请不要回答您的问题:我不知道是否存在数学上更可靠的解决方案,并且同样渴望知道过去的大师们所做的事情:)在那之前,至少我们有一个骇人听闻的技巧来保持我们的代码正常运行。
编辑
我可能应该涵盖仅简单压缩信号的问题中给出的解决方法。因为在边缘情况下平均值不是线性的,所以简单地压缩输入信号不会产生理想的结果-尽管它确实可以修复端点:
参考文献