我如何创建即使经过一百万次运行也不会损坏图像的过滤器-第2部分

图片

图片

在这篇文章的第一部分中 ,我谈到了如何重复使用标准的Halfpel滤镜会导致图像失真,然后展示了一个没有此问题的新滤镜。

这有点模糊,这并不适合所有人。 但是,它比其替代产品要好-实际上,此过滤器是在原始版本的Bink 2中使用的 。 由于工作量的不断增加,我再也没有设法回到他身边并对其进行详细检查。

但是,既然我已经时间返回该过滤器并撰写有关该过滤器的文章,那么我终于要问一个问题:是否有一个模糊程度更低的过滤器仍然保留了“无限稳定性”属性?

剧透警告:正确的答案是“可能不会”和“肯定在那里”。 但是在弄清楚为什么对这个问题有两个答案以及它们的含义之前,让我们更好地准备一个测试平台。

偏移调整


当我最初研究此问题时,我不知道自己在寻找什么。 我什至不知道一个“无限稳定”的半球滤波器,所以我没有在它的搜索中创建一个系统。 我只是在寻找可以承受“多次”滤镜迭代而不会造成图像失真的东西。 第一部分中的所有图像都反映了这种方法:图像一次从右移到左半像素,即,如果您应用滤镜100次,则生成的图像将移位50像素。

既然我们知道了实际要寻找的东西 ,我们可以更加精确一些。 应用两次半像素滤镜,我们将图像精确移动一个像素。 也就是说,如果我们仅将图像向后移动一个像素 ,那么它将保留在相同的空间中。 由于这个原因,测试看起来会更加漂亮,因为这样我们不仅可以多次应用滤镜,而不必担心图像会从屏幕上``爬开'',而且我们还能找到图像与以前版本和原始图像的差异

这将使我们能够自动测试过滤器。 我们简单地多次应用滤镜并看到以下两件事之一:要么收敛到未更改的图像(表明滤镜是无限稳定的),要么与原始图像有很大的偏差(表明滤镜“损坏”)。 对于这些测试,我选择了每个通道64的平均误差(255个中的最大误差),或者将全部255个通道中的最大误差选择为“相当大”。如果这些条件中的任何一个成立,我们将假定滤波器为“ broke” ”。

从第一部分重新测试过滤器


因此,现在我们更好地了解了如何测试这些过滤器,因此让我们重新看一下第一部分中的过滤器。 让我们从双线性开始,这当然不是很有趣:


这是244次迭代后的图片。 如您所料,由于像素的不断平均,图像逐渐“破裂”。 但是,即使它逐渐达到平均误差的极限。

这是h.264:


要打破形象,他需要进行78次迭代。 具有8个样本的HEVC过滤器的性能要好一些,但在150次迭代后仍然会中断:


166次迭代后,带有6个样本的Lanczos中断:


这就是我们所有损坏的过滤器。 剩下的就是我的整数过滤器:


不出所料,他不是唯一一个要打破的人。 经过208次迭代,它收敛到无限稳定的图像。

我们在这里所知道的是非常出色的:至少对于广泛的测试图像,该滤镜是无限稳定的 ,也就是说,无论使用多少次,它都不会产生伪像。

这使我们回到了最初的问题:他真的是最好的吗? 您已经知道答案了,因为在本文开头,我还写道:“可能不会”和“肯定会”。

让我们首先来看“可能不是”部分。

整数过滤器


因此,在文章的第一部分中,我提到我发现的过滤器芯是“检测到的最好的”,这就是它的独特之处。 这里是功能:

实际上 ,当我寻找此过滤器时,我并不是在寻找最佳过滤器。 我一直在寻找可以用极少量的整数移位,加法和减法表示的最佳滤波器。 可能看起来很奇怪,但是要花点时间。

您可能已经注意到,当我显示h.264,HEVC和双线性滤波器的系数以及滤波器时,我将它们记为整数分母,写成整数分母,如下所示:

MyKernel[] = {1.0/32.0, -4.0/32.0, 19.0/32.0, 19.0/32.0, -4.0/32.0, 1.0/32.0}; 

但是在窗口窗口的情况下,我的行为有所不同,并这样写:

 LanczosKernel[] = {0.02446, -0.13587, 0.61141, 0.61141, -0.13587, 0.02446}; 

其原因是因为窗口Sinc实际上是从与普通整数分数无关的连续数学函数推断出来的。 使用此滤波器时,将使用与sinc函数的值相对应的浮点数(尽可能准确)。 如果您努力准确地应用它们,则不应将它们四舍五入为普通分数,因为这会增加错误。

传统上,视频编解码器无力执行此类操作。 在诸如运动补偿之类的“繁重”任务上进行浮点运算根本不可能在低功率或专用设备上使用。 如果我们正在谈论应在多种设备上运行的行业标准编解码器,则尤其如此,包括低成本,低成本嵌入式芯片。

而且,即使您在CPU上执行它们,现代指令集也基于SIMD,也就是说,CPU上的整数运算仍然可以更快地执行:您可以将两个16位整数放入一个32位浮点数的空间中,从而使操作性能实质上提高了一倍,因此,如果我们考虑每次操作的确切周期数,那么浮点数并不总是最快的选择。

现在您将了解为什么此功能很重要。 由于我只需要简单的16位整数运算,因此我寻找了那些可以以除数表示的小整数形式的内核,其取值范围为2到64,而没有更多。 与我考虑的任何一组6个浮点系数相比,这组滤波器要有限得多。

同样,出于效率考虑,我没有考虑其他数量的样本。 唯一的选择是6个或更少,因此我什至没有测试8个或10个样本的版本。

因此,我们得出了第一个答案:“可能不会。” 如果我们遵守这些限制,那么很可能我们将找不到更好的过滤器,可以无限次地应用而不会降低性能。 尽管我必须承认我无法详尽地证明它,但第一部分中的滤波器核心可能是我们能找到最好的。

但是,如果我们不需要遵守这些限制怎么办?

浮点版本


如果我们摆脱了Bink 2原始版本(现在已经过时-已发布了许多修订版)特有的限制,并使用了任意浮点系数,我们如何改善结果?

好吧,因为我们知道我的整数内核永远不会退化,而且我们知道Lanczos会更锐利但会退化,因此逻辑上我们可以两组系数之间找到一个开始退化的位置,这是合乎逻辑的。 因此,我写了一个程序来帮助我找到这一点,这就是我发现的内核:

 MyFloatKernel6[] = {0.027617, -0.130815, 0.603198, 0.603198, -0.130815, 0.027617}; 

该内核需要272次迭代才能收敛,但是它是无限稳定的,并且比我的整数滤波器清晰得多:


实际上,它与原始版本几乎没有区别:


差不多...但不完全是。 如果仔细观察,仍会在高对比度区域看到模糊和衰减。 最简单的方法是在橙色“恐龙”的眼中以及竹子后面的明亮区域。

也就是说,使用6采样点的浮点滤波器绝对更好,但并不完美。 可以改善吗?

增加过滤器宽度


最初,出于与小整数部分相同的原因,选择了一个包含6个样本的过滤器:我一直在寻找一种效率极高的过滤器。 但是现在我们正在研究,并且已经开始使用浮点数,那么为什么不考虑使用更宽的滤波器呢?

将我们的6样本整数滤波器与6样本Lanczos相结合,我们得到了一个非常好的滤波器。 我们为什么不将其与8个样本的Lanczos配对?

8个样本的Lanczos看起来像这样:

 Lanczos8[] = {-0.01263, 0.05976, -0.16601, 0.61888, 0.61888, -0.16601, 0.05976, -0.01263}; 

像6个样本的Lanczos一样,它非常不稳定,并且在178次迭代后崩溃:


如果我们在6样本整数过滤器和8样本Lanczos之间寻找更好的过滤器,我们会发现这个相当出色的8样本过滤器:

 MyFloatKernel8[] = {-0.010547, 0.052344, -0.156641, 0.614844, 0.614844, -0.156641, 0.052344, -0.010547}; 

作为一个无限稳定的滤波器,它的表现非常出色。 它在202次迭代后收敛(收敛比我的两个滤波器快),并且与原始滤波器非常相似,因此很难确定哪个是哪个:


这是原始文件,供再次参考:


与我原来的整数滤波器相比,有了很大的改进。

无限稳定的滤波器如何工作?


我打算结束这篇文章,像这样:

“我不知道这一切如何运作。 在我从事无限适用转换的其他领域,我知道如何执行边界数学和创建有用的分析。 首先,分析细分表面的边界表面,计算细分矩阵的特征值和特征向量,然后可以精确地将极限取到无限大。 但是我没有对半像素滤镜进行这种分析的经验,因为它们不会将像素留在适当的位置,而是将其侧向移动。”

那是我的计划。 但是在第一部分和第二部分之间,我将改进的过滤器的结果邮寄给了Fabien GiessenCharles Bloom他们知道这一问题的分析研究所必需的数学不足为奇。 事实证明,对于滤波器,实际上是对特征值和向量进行了分析,但并非完全如此。

但这很容易做到-实际上,它是作为一个简单的一步过程内置在CAM程序中的,我们可以真正查看滤波器的特征值。 他没有给我们完整的答案,因为在这里,每次滤波后四舍五入到8位(或10位或12位)的事实很重要,因为与无限精确的代数相比,截断会影响累积误差的方法。

不幸的是,由于这并不是我的专长,因此我什至无法对此分析进行详尽的概述。 我问Fabien和Charles是否可以写出邮件中发给我的好信息(他们俩都有技术博客-ryg博客cbloom rants ),然后Fabien 在稳定过滤器的数学基础上写了一系列精彩的文章 。 如果您对我的两篇文章中所发生的事情的理论结构感兴趣,那么建议您阅读本系列!

Source: https://habr.com/ru/post/zh-CN468629/


All Articles