这个算法叫什么名字?与其他图像重采样算法相比如何?

11

这个算法在我脑海中已经有很久了,但我找不到任何描述它的地方。虽然它非常简单,但我肯定不是唯一想到它的人。以下是它的工作方式:

你从一个图像开始。比如说,7x7像素:

Algorithm 1

你需要将其重新采样为,比如5x5像素:

Algorithm 2

所以你要做的就是取每个新正方形的平均颜色:

Algorithm 3

这不是最近邻算法,因为它只取一个像素的颜色,而不是覆盖源像素的分数像素的颜色。它也不是双线性、双三次、Lanczos或其他插值算法。

那么——它是什么?在我的直觉中,这应该是“数学完美”的重采样算法,尽管由于我没有“数学完美”的定义,我无法证明或否定这一点。

最后但并非最不重要的,“数学完美”并不总是“最好看的”,因此我想知道它与其他主流图像重采样算法(双三次、Lanczos)在“质量”方面有何区别?当然,这是一个主观的术语,所以我真的很感兴趣是否有显着的差异,大多数人都会同意这一点。

P.S. 我已经可以确定几件事——它不适用于像素艺术,如此例所示;有专门的算法来解决这个问题(2xSAI等);对于放大图片,它也不是最好的选择——插值会胜出。但是对于缩小图片呢...?

更新 1:嗯,刚刚发现了超级采样。这似乎是一种它的变体,使用网格状排列的样本,其中样本数量优化了源图像和目标图像的分辨率。


平均化是一种非常差的低通滤波器(即抗混叠滤波器),因此我预计结果会比使用更好的滤波器的大多数其他方法要劣。 - Paul R
@PaulR - 即使是在降采样时? - Vilx-
是的,这就是整个重点 - 理想情况下,在抽取之前需要进行完美过滤,否则会出现混叠和/或信息丢失。平均实际上是一个非常糟糕的低通滤波器,在通带中不太平坦,在阻带中有大的旁瓣。 - Paul R
2
@PaulR - 哇...好的...我想我最终还是需要去读一下有关信号和图像处理的书籍。 :P - Vilx-
1
你是对的,你并不是第一个 - 我在25年前就使用了这个技术,我肯定也不是第一个。我没有为它取名字。它很容易实现,并且优化效果非常好。如果要看它与更好的过滤器相比如何失败,请将大图像调整为比一个像素小 - 边缘将会很清晰,但中心部分将会模糊。 - Mark Ransom
5个回答

3
你所提到的算法被称为区域平均算法,它很少用于缩小图像。其中一种更简单的变体被用作计算机游戏中渲染图像的抗锯齿技术。 该技术的算法称为超采样

enter image description here

感谢 @Guffa 指出,这是上述算法的简化版本,因为它采样点可能会错过某些颜色,或者选择一个颜色比另一个更多次,即使它不是最显著的。
上述算法等同于超级采样算法的无限点采样。 更新: 刚刚注意到,即使是Java也欣赏您的算法 :)
AreaAveragingScaleFilter

不,超采样是 OP 所谈论的算法的简化版本。由于您在特定位置取样而不考虑到目标像素的距离,因此会产生舍入误差。 - Guffa
@Guffa:他既没有考虑到目标像素的“距离”,超采样也没有考虑到。此外,超采样没有目标像素,因为它通过对其内部采样点进行采样来渲染一个像素。 - Yarneo
@Guffa - 超采样可以用来精确地获得这种效果。你只需要有正确的采样位置即可。 - Vilx-
如果您采集无限数量的样本,则结果将是正确的。样本越少,误差就越大。如果算法考虑源像素的位置,并权衡源像素和目标像素之间的距离,即使使用很少的样本也可以得到数学上完美的结果。目标像素就是您所说的“一个像素”。 - Guffa
1
@Vilx-:是的,如果你从基于图像大小的网格中取样,你可以得到正确的结果。在你的例子中,你需要每个像素1225个样本(35*35)才能得到完全正确的结果。这很快就会失控...例如,将一个1000x1000的图像重新采样为999x999需要每个像素998001000000个样本。 - Guffa
@Guffa - 嗯,我没有考虑过那个。:P 我以为样本数量会更容易处理。不过,它可以被优化为每个重叠的源像素执行一个加权采样。 - Vilx-

3
我首先要说的是,我不知道您算法的官方名称。我知道Paint Shop Pro最初称其为“双线性”,但在第8版中被迫将其重命名为“加权平均”,因为有人指出该算法与双线性的经典定义不符。
大多数调整大小算法可以分别应用于X和Y两个独立的传递。这不仅更有效,而且使描述和推理不同算法变得容易得多。从现在开始,我将在一个维度上工作,并假设您可以推断到2D。
您的输入由7个像素组成,我们将给出0、1、2、3、4、5、6的坐标。在这种情况下,有用的是要意识到像素不是一个小正方形,而只是一个单点。为了创建输出,您需要从点0.2、1.6、3.0、4.4、5.8获得插值值。为什么不是0.0、1.5、3.0、4.5、6.0呢?假设您将输入和输出的大小加倍到14x14和10x10:现在的坐标是0.0、1.44、2.89、4.33、5.78、7.22、8.67、10.11、11.56、13.0。从第二个像素开始,结果会有所不同,这是不可接受的。所有点应该相隔7/5,给出坐标0.2、1.6、3.0、4.4、5.8、7.2、8.6、10.0、11.4、12.8。

让我们将常见的调整大小算法表达为滤波器进行比较,看看它们与您的算法相比如何。

Nearest Neighbor filter

这个泛型形式的第一个例子被称为盒式或平均滤波器。但当盒式滤波器的宽度恰好为1.0时,神奇的事情发生了:输入中的一个像素将落在盒子内,并被赋予1.0的权重,而输入中的所有其他像素都被赋予0.0的权重。这使得它等同于最近邻算法。

Bilinear filter

我们的第二个例子通常被称为帐篷滤波器。当宽度恰好为2.0时,它变成了线性插值,应用于2D则称为双线性插值。请注意保留HTML标签。

Bicubic filter

第三个例子是Cubic滤波器,在2D中应用时称为Bicubic。这个公式有不同的变化,这个例子使用了Mitchell和Netravali建议的变化。

Gaussian filter

尽管高斯滤波器在调整大小的应用中并不常用,但我在这里添加它进行比较。

Weighted Average filter

最后我们来到了你的算法。它是平均和双线性的组合,形状像一个带有平顶的帐篷。


希望我能给你更多的赞,既因为详细的分析,也因为提供了链接。虽然有点过时,但我理解了重点。我想需要一些时间来重新调整我的思维方式。此外,很明显我需要提高数学技能并阅读有关采样定理/图像处理的资料。 :P - Vilx-
@Vilx- 我花了很多年才深入理解这些东西,即使在我停止每天使用它们之后。不要自责。我想发布这个答案的原因之一是我从未看到经典算法以如此直接的方式表达为过滤器,我认为这真的有助于比较它们。 - Mark Ransom

1
与我在其他答案中所读到的相反,这个算法在超采样方面实际上相当受欢迎,至少在图像处理社区中是如此。它在英特尔性能原语库中被实现,名称为Super Sampling;这个(相当没有信息量的)名称是一种表明该库中没有替代超采样算法的方式。在OpenCV中,它被称为INTER_AREA;它被列在其他插值类型中,这可能表明它们是可以互换的,但提到“它可能是图像缩减的首选方法”——对我来说是一个相当保守的说法。
当你将图像按整数倍超采样,例如两倍,对于生成的图像取底层像素的平均值(例如通过scikit-imagedownscale_local_mean完成)在特定意义下确实是最优的。假设您的图像是通过对网格接收器中的信号进行某种定量测量获得的。例如,照片或X射线,计算光子数量。像素值与给定接收器接收到的信号量成比例。如果您假设您的相机是完美的 - 信号没有扩散,接收区域100%覆盖 - 那么平均超采样是最优的,因为它提供了半分辨率的完美相机所接收到的精确图像。面积平均是这种最佳平均超采样的直接推广到非整数比率,这解释了它的流行,尽管它不能为除整数以外的任何超采样比率提供相同的属性。

0

你的描述并不让我想起一个算法,很可能是数据结构和数据类型。它让我想起了kd-tree或者quadtree。使用kd-tree或者quadtree可以帮助你解决最近邻问题。但是如果你想要一个用于网格的数学函数,你也可以看看填充空间曲线,特别是z-order莫顿曲线。这对于2的幂非常有效,并且可以减少二维复杂度。该函数为f(x,y) = (f(x), f(y))。


-2

实际上,它是双线性的。双线性重采样只是在两个维度上进行线性插值。

您将其描述为获取像素表面的平均颜色,但从周围像素进行插值只是计算相同值的更简单的方法。

插值是一次完成一个维度,因此您只需计算重叠的边缘而不是重叠的区域,这要简单得多。


如果目标像素重叠了许多源像素怎么办?如果我正确理解维基百科的话,它说双线性插值仅使用位于对角方向上的4个最近像素值来查找给定像素的适当颜色强度值 - Vilx-
1
@Vilx- 这个答案几乎正确,但并非完全正确。考虑你示例中的中心像素 - 它在两个图像中都对齐,因此按双线性插值的规则,它应该完全从该中心像素获取其值,而不是从周围像素中获取任何值。你的方法包含了每个周围像素的一小部分。 - Mark Ransom
1
@Guffa,线性插值是两个点之间的一条直线上的一个点。它不能超过两个点,否则就不是线性的了。你的图片非常准确,恰好展示了我所说的中心点对齐的情况。 - Mark Ransom
1
@Guffa,线性插值只在两个点之间进行,超过2个点就不算了。双线性插值则是在4个点之间进行,即2x2。问题中提供的示例使用了9个像素的部分来创建中心像素,这绝对不是双线性插值。像你在答案中所说的那样称其为双线性插值是错误的。 - Mark Ransom
1
@Guffa,你错了——双线性插值确实只使用线性插值。请阅读你自己的文章。 - Mark Ransom
显示剩余15条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接