计算GPU上的图像相似度[OpenGL / OcclusionQuery]

时间:2020-03-06 14:24:50  来源:igfitidea点击:

OpenGL。假设我先绘制了一张图像,然后使用XOR绘制了第二张图像。现在,我在某个地方有非黑色像素的黑色缓冲区,我读到可以使用着色器在GPU上计算黑色[rgb(0,0,0)]像素吗?

我还读到它必须与OcclusionQuery一起做一些事情。
http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt

有可能吗? [任何编程语言]

如果我们还有其他关于如何通过OpenGL / GPU查找相似性的想法,那也很好。

解决方案

我不确定我们如何执行XOR位(至少它应该很慢;我不认为任何当前的GPU会加快XOR位),但这是我的主意:

  • 有两个输入图像
  • 打开遮挡查询。
  • 使用片段着色器将两个图像绘制到屏幕上(即设置了两个纹理的全屏四边形),该片段着色器计算abs(texel1-texel2),并在像素相同(差值为零或者低于某个阈值)。最简单的方法可能只是使用GLSL片段着色器,然后我们就可以读取两个纹理,计算差异的abs()并丢弃像素。在这里,非常基础的GLSL知识就足够了。
  • 获取通过查询的像素数。对于相同的像素,查询将不通过(像素将被着色器丢弃),对于不同的像素,查询将通过。

起初,我虽然采用了涉及深度缓冲区的更复杂的方法,但随后意识到仅杀死像素就足够了。虽然这是我的原始作品(但上面的内容更简单,更有效):

  • 有两个输入图像
  • 清晰的屏幕和深度缓冲区
  • 使用片段着色器将两个图像绘制到屏幕上(即设置了两个纹理的全屏四边形),该片段着色器计算abs(texel1-texel2),如果像素不同则杀死像素(在GLSL中丢弃)。绘制四边形,使其深度缓冲区的值接近于近平面。
  • 在此步骤之后,深度缓冲区将为相同的像素包含较小的深度值,而为不同的像素包含较大(远平面)的深度值。
  • 打开遮挡查询,然后绘制另一个全屏四边形,其深度比远平面更近,但大于前一个四边形。
  • 获取通过查询的像素数。对于相同的像素,查询将不通过(深度缓冲区已经接近),对于不同的像素,查询将通过。我们将使用SAMPLES_PASSED_ARB来获取此信息。 CodeSampler.com上有一个遮挡查询示例,供我们入门。

当然,所有这一切都需要具有遮挡查询支持的GPU。自2002年左右以来,大多数GPU都支持该功能,除了一些低端GPU(特别是Intel 915(aka GMA 900)和Intel 945(aka GMA 950))。