如何通过线性插值实现快速的Catmull-Rom纹理过滤?

3

我读过一些介绍使用GL_LINEAR进行快速三阶插值的文章。

因为[1]中有很多勘误,如果您想了解公式,我建议阅读[2]。

它们两个都提到了这种方法的限制。对于使用GL_LINEAR进行过滤的纹理,下面的关系成立仅当0 <= b/(a+b) <= 1

a*f(i, j) + b*f(i+1, j) = F(i+b/(a+b), j)

其中f是原始图像数据,F是OpenGL线性插值的纹理。

这里的问题是[1]提到了这种方法也可以应用于Catmull-Rom三次样条。然而,显然用包含负部分的Catmull-Rom加权函数,条件(0 <= b /(a + b)<= 1)无法满足。事实上,我尝试使用相同的逻辑实现Catmull-Rom,但只会产生模糊的图像。是否有一种特殊的方法可以将[1]和[2]中的方法应用于Catmull-Rom插值?还是我必须获取所有16个纹理元素来进行Catmull-Rom插值?
1个回答

1
我认为Sigg和Hadwiger的论文是正确的。
Catmull-Rom多项式p(t)可以写成:
p(t) = 0.5 [ w0(t) * p0 + w1(t) * p1 + w2(t) * p2 + w3(t) * p3]

where

w0(t) = -t + 2*t^2 - t^3;
w1(t) = 2 - 5*t^2 + 3*t^3;
w2(t) = t + 4*t^2 - 3*t^3;
w3(t) = -t^2 + t^3;

p0p1p2p3 则是采样函数的值。

对于B样条,您将前两个项(即和)和后两个项(即和)分组。对于Catmull-Rom样条,您将和以及和分组在一起。很容易通过Matlab绘图来验证条件b/(a+b)是否满足这个选择。因此,这个想法也可以用于Catmull-Rom插值。但是,对于Catmull-Rom情况,我认为最后一步没有可能的扩展,因为既不是<(w0(t)+w3(t))/(w0(t)+w1(t)+w2(t)+w3(t))>也不是<(w1(t)+w2(t))/(w0(t)+w1(t)+w2(t)+w3(t))>符合您指定的条件。

感谢您的回复。就我理解的文章而言,两个像素必须相邻才能使用该公式。在您的回复中,p1和p2是最近的邻居,因此可以通过一次纹理获取获得w1p1+w2p2。然而,p0和p3不是最近的邻居。您认为是否可以通过一次纹理获取来获得p0和p3的加权和? - slyx
很抱歉,我不是OpenGL的专家。在CUDA中,纹理内存被优化为本地访问,我认为所有这些数据都可能驻留在纹理缓存中,因此只需要一次纹理获取即可。也许OpenGL会类似。 - Vitality
在OpenGL中,纹理获取意味着获取给定坐标的过滤后(在这种情况下是线性插值)的颜色(纹理数据)。因此,基本上每个像素值都需要进行一次纹理获取,要获取四个像素,我必须获取四次纹理。文章的关键点是通过使用线性插值过滤纹理将这些纹理获取从4次减少到2次。 - slyx

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