OpenGL 超分辨率问题
Posted
技术标签:
【中文标题】OpenGL 超分辨率问题【英文标题】:OpenGL Super Resolution issues 【发布时间】:2016-06-28 06:18:45 【问题描述】:我有一个基于 OpenGL 的 gui。我使用超分辨率能够处理各种比例。不是放大图像,而是缩小图像(除非碰巧有人以 4000x4000+ 分辨率运行)。
问题是,OpenGL 似乎并不能顺利缩减。我有工件,好像缩放是最近的邻居。 (例如,文本边缘是块状的,即使它们不在原始文件中)
这些是我使用的设置:
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
这是一个工件样本,我相信比例是 2:1。由于窗口边缘等原因,可能并不准确。
您可以看到左边缘看起来很完美(虽然不是这样),但右边缘有奇怪的中断。原始图形完全对称,没有伪影。
我试过 GL_NEAREST、GL_LINEAR。没有 mipmapping 所以...
OpenGL 在缩放方面肯定不是那么差吗?我想要双三次缩放之类的东西或能产生良好结果的东西。
我使用的是 OpenGL 1.1。我可能会预先缩放图像,但每次窗口大小发生变化时我都必须这样做,并且 cpu 可能会很慢。
我在一些图像上也有锯齿状边缘。超分辨率的全部意义在于避免这一切;/
我缺少一些设置吗?
【问题讨论】:
超分辨率有点误导,因为您担心下采样。然而,从最近变为线性,您应该会看到小比例的差异,例如原始的 1/1.2。GL_NEAREST
肯定是最近邻插值。
【参考方案1】:
首先,您必须了解信号理论,即Nyquist Theorem(该***页面在谈论“时间”域中的信号时过于具体;该原理对于所有类型的离散采样信号(包括图像)都是通用的)。在进行下采样时,您始终必须应用lowpass anti aliasing filter,它会切断采样频率一半以上的所有频率分量,以避免产生混叠伪影。如果没有过滤,即使是线性积分下采样器也会产生伪影。实现纹理低通滤波器的实时图形方式是mipmaps。每个 mipmap 级别的截止频率恰好是下一个更高级别的频率的一半。
你现在有两个选择:
实现 mipmapping 实现下采样片段着色器当然,明智的做法是首先不要以过高的分辨率进行渲染,而是以完全目标分辨率来渲染你的 GUI。
【讨论】:
【参考方案2】:根据你提供的代码,我会猜测可能是什么问题。
尝试加载您的图像或至少分配内存在您使用glParameteri
设置这些纹理参数之前。另外,将GL_TEXTURE_MIN_FILTER
设置为GL_LINEAR
也许您的意思是超级采样 (SSAA),它使用原始分辨率的 2 倍或更多倍并对其进行下采样以获得平滑的图像?
【讨论】:
【参考方案3】:从您的图像中可以看出它正在使用线性过滤(双线性) 尝试使用各向异性过滤:
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
各向异性过滤可以应用于不同的级别,此代码将应用到最大级别,如果您愿意,可以使用小于aniso
的数字。这些是扩展宏,如果你没有扩展定义,它们是这样的:
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
【讨论】:
以上是关于OpenGL 超分辨率问题的主要内容,如果未能解决你的问题,请参考以下文章