【问题标题】:Where can I find a good read about bicubic interpolation and Lanczos resampling?我在哪里可以找到有关双三次插值和 Lanczos 重采样的好读物?
【发布时间】:2010-10-30 22:28:11
【问题描述】:

我想在 C++ 中实现上述两种图像重采样算法(双三次和 Lanczos)。我知道那里有几十个现有的实现,但我仍然想自己做。我想实现它,部分原因是我想了解它们的工作原理,部分原因是我想为它们提供一些主流实现中没有的功能(例如可配置的多 CPU 支持和进度报告)。

我尝试阅读维基百科,但内容对我来说有点太枯燥了。也许对这些算法有更好的解释?我在 SO 或 Google 上都找不到任何东西。

补充:似乎没有人能给我一个关于这些主题的好链接。至少有人可以在这里解释一下吗?

【问题讨论】:

    标签: algorithm image-processing resampling


    【解决方案1】:

    这两种算法的基本操作原理都很简单。它们都是卷积滤波器。一个卷积滤波器,它针对每个输出值将卷积函数的原点移动到以输出为中心,然后将输入中的所有值与该位置的卷积函数的值相乘,然后将它们相加。

    卷积的一个特性是输出的积分是两个输入函数的积分的乘积。如果考虑输入和输出图像,那么积分意味着平均亮度,如果您希望亮度保持不变,卷积函数的积分需要加一。

    理解它们的一种方法是将卷积函数视为显示输入像素根据距离影响输出像素的程度。

    卷积函数通常被定义为当距离大于某个值时它们为零,这样您就不必考虑每个输出值的每个输入值。

    对于 lanczos 插值,卷积函数基于 sinc(x) = sin(x*pi)/x 函数,但只取前几个波瓣。通常为 3:

    lanczos(x) = {
        0 if abs(x) > 3,
        1 if x == 0,
        else sin(x*pi)/x
    }
    

    这个函数称为过滤器内核。

    要使用 lanczos 重新采样,假设您将输出和输入相互叠加,点表示像素位置的位置。对于每个输出像素位置,您从该点取一个框 +- 3 个输出像素。对于位于该框中的每个输入像素,计算该位置的 lanczos 函数的值,并将输出像素坐标中与输出位置的距离作为参数。然后,您需要通过缩放计算值来归一化计算值,使它们加起来为 1。然后将每个输入像素值与相应的缩放值相乘,然后将结果相加得到输出像素的值。

    因为 lanzos 函数具有可分离性,并且如果您正在调整大小,网格是规则的,您可以通过分别进行水平和垂直卷积来优化这一点,并预先计算每行的垂直过滤器和每列的水平过滤器。

    双三次卷积基本相同,只是滤波器核函数不同。

    要获得更多详细信息,请参阅Digital Image Processing 16.3 节中的非常好的和彻底的解释。

    此外,skia 中的image_operations.ccconvolver.cc 对lanczos 插值的实现进行了很好的评论。

    【讨论】:

    • err,你对内核的定义不太对,应该是 3*sin(pix)*sin(pix/3)/(pi pix*x) (对于 lanczos3...)
    【解决方案2】:

    虽然 Ants Aasma 所说的大致描述了差异,但我认为它并不能特别说明您为什么会这样做。

    就链接而言,您在图像处理中提出了一个非常基本的问题,任何关于该主题的体面的入门教科书都会对此进行描述。如果我没记错的话,Gonzales and Woods 是不错的,但我远离我的书,无法检查。

    现在谈谈细节,从根本上考虑你在做什么应该会有所帮助。您有一个要为其插入新值的测量方格。在简单的上采样案例中,假设您希望在已有的每个测量值之间进行新的测量(例如,将分辨率提高一倍)。

    现在您不会得到“正确”的值,因为通常您没有该信息。所以你必须估计它。这个怎么做?一种非常简单的方法是线性插值。每个人都知道如何用两个点来做到这一点,你只需在它们之间画一条线,然后读取线外的新值(在这种情况下,在中间点)。

    现在图像是二维的,所以你真的想在左右和上下方向上都这样做。将结果用于您的估计,瞧,您有“双线性”插值。

    这样做的主要问题是它不是很准确,尽管它比“最近邻”方法更好(而且更慢),后者也非常局部且快速。

    要解决第一个问题,您需要比两点的线性拟合更好的东西,您想要将一些东西拟合到更多数据点(像素),以及一些非线性的东西。精度和计算成本的一个很好的权衡是所谓的三次样条。因此,这将为您提供一条平滑的拟合线,并再次通过中间的值来近似您的新“测量值”。在两个方向上都这样做,你就得到了“双三次”插值。

    所以这更准确,但仍然很重。解决速度问题的一种方法是使用卷积,它具有很好的特性,在傅里叶域中,它只是一个乘法,所以我们可以很快地实现它。但是您无需担心实现,以了解任何时候的卷积结果都是一个函数(您的图像)被集成到另一个产品中,通常支持更小的支持(非零部分)称为内核的函数),在该内核以该特定点为中心之后。在离散世界中,这些只是产品的总和。

    事实证明,您可以设计一个具有与三次样条非常相似的属性的卷积核,并使用它来获得快速的“双三次”

    Lancsoz 重采样是类似的事情,内核中的属性略有不同,这主要意味着它们将具有不同的特征工件。您可以轻松地查找这些内核函数的详细信息(我确信维基百科有它们,或任何介绍文本)。图形程序中使用的实现往往是高度优化的,有时有专门的假设,使它们更高效但不太通用。

    【讨论】:

      【解决方案3】:

      我想推荐以下文章,以基本了解不同的图像插值方法image interpolation via convolution。如果你想尝试更多的插值方法,imageresampler 是一个不错的开源项目。

      我认为图像插值可以从两个方面来理解,一个是从函数拟合的角度,一个是从卷积的角度。例如,image interpolation via convolution 中解释的样条插值在Cubic interpolation 中从函数拟合的角度得到了很好的解释。

      此外,图像插值始终与特定应用相关,例如图像缩放、图像旋转等。事实上,对于特定的应用程序,图像插值可以以一种智能的方式实现。例如,可以通过three-shearing method 实现图像旋转,并且在每次剪切操作期间可以实现不同的一维插值算法。

      【讨论】:

        猜你喜欢
        • 2014-02-28
        • 1970-01-01
        • 2013-03-25
        • 2010-09-14
        • 2010-11-04
        • 2011-08-06
        • 2010-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多