Python OpenGL中的亚像素渲染-精度问题

Python OpenGL中的亚像素渲染-精度问题,python,opengl,pyglet,Python,Opengl,Pyglet,我需要为摄影测量应用程序生成几个系列的测试图像。 这些应该包含具有非常精确的已知位置的简单对象(磁盘、矩形等) 考虑到白色背景上黑色矩形的8位灰度图像,最小可观察位移(插值后)应为1/256像素,因为每个像素有256个可能的强度级别 我决定使用OpenGL(使用python+pyglet)来渲染这样的图像,因为稍后我将不得不渲染更复杂的图像(3d场景、立体图像对) 不幸的是,我获得的最佳精度大约是像素/10,没有使用完整的强度深度 是否有可能做得更好,理想情况下-达到1/256像素的精度?有没有

我需要为摄影测量应用程序生成几个系列的测试图像。 这些应该包含具有非常精确的已知位置的简单对象(磁盘、矩形等)

考虑到白色背景上黑色矩形的8位灰度图像,最小可观察位移(插值后)应为1/256像素,因为每个像素有256个可能的强度级别

我决定使用OpenGL(使用python+pyglet)来渲染这样的图像,因为稍后我将不得不渲染更复杂的图像(3d场景、立体图像对)

不幸的是,我获得的最佳精度大约是像素/10,没有使用完整的强度深度

是否有可能做得更好,理想情况下-达到1/256像素的精度?有没有关于如何做的提示

生成部分磁盘图像的示例代码在每帧中多移动了0.01像素

#-*- coding: utf-8 -*-
import pyglet
from pyglet.gl import *
from PIL import Image, ImageGrab

config = pyglet.gl.Config(width = 800, height = 600, sample_buffers=1, samples=16)
window = pyglet.window.Window(config=config, resizable=True) 
window.set_size(800, 600)

printScreenNr = 0

@window.event
def on_draw():
     global printScreenNr
     window.clear()
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

     glLoadIdentity()
     glEnable(GL_LINE_SMOOTH)
     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

     glTranslated(200, 200,0)

     circleQuad = gluNewQuadric()
     glTranslated(200+(printScreenNr*0.01), 0, 0)
     gluPartialDisk(circleQuad, 0, 50, 500, 500, 0, 180)

@window.event
def on_resize(width, height):
    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho (0, width, height, 0, 0, 1);
    glMatrixMode(GL_MODELVIEW)
    return pyglet.event.EVENT_HANDLED

@window.event
def on_text(text):
    global printScreenNr
    if(text == "p"):
        pyglet.image.get_buffer_manager().get_color_buffer().save('photo'+str(printScreenNr)+'.tiff')
        printScreenNr += 1

pyglet.app.run()

(上面的代码使用gluPartialDisk,但我也使用四边形测试了这个问题,结果的准确性没有差异)

一个简单的方法是按比例缩放图像。如果将图像缩放4.0,则16个原始像素将合并为一个目标像素,在缩放纯黑白图像时,该目标像素将提供16个灰度阴影

但有一个陷阱可能解释了你的问题。如果您有:

  ...#####
  ...#####
  ...#####
  ...#####
(左:白色,右:黑色填充矩形),则有12个白色像素和4个黑色像素构成单个输出像素。要获得1个黑色像素,输入需要如下:

  ....####
  ....####
  ....####
  ...#####

看到了吗?即使黑匣子只在空白处漏出一个像素,它也会漏出四次。因此,为了确保子像素渲染代码正常工作,您需要查看单个像素或角点,而不是边缘。

即使使用正交投影,GL_透视图_校正提示可能会影响渲染精度。至少我模模糊糊地记得glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);多年前,在我的正交投影场景中修复了一些间隙。

您是否尝试过使用32位颜色深度?我之所以这样说,是因为32位路径是当今图形驱动程序中使用最多、维护最多的代码路径。如果这样做有效,您可以在之后执行高质量的颜色深度重缩放。尝试过,但没有更改结果。。。不过,谢谢你,谢谢你,补充说,目前没有改变结果,但在未来的3d现代化中可能需要一个更大的图像是一个解决方案,但我认为屏幕的大小是一个限制?所以这对你答案的另一部分没有多大帮助,我不确定我是否理解正确。。。如果图像已缩放4倍(在每个方向上),则在观察边缘时可提供4种可能的阴影(在观察点时为16种),但仍然可以生成以全深度精度定位的边缘。如何?边缘只有四个不同的位置,所以你只能得到16个阴影中的4个。如果我仍然错了,请纠正我。让我们假设图像已缩放256倍。一条边将有256个位置,一个点:256^2(将被四舍五入)。我不知道,在OpenGL中是否可以做这样的事情(在这种情况下,性能不是问题),但我认为满足这些要求的图像通常可以生成。我的问题是:如何做到这一点..您可能希望按16(16x16=256)进行缩放。渲染为屏幕外纹理,然后将纹理缩放到与屏幕完全匹配的矩形上。感谢您提供的屏幕外纹理建议。然而,我不想缩放16-我需要在每个方向上至少0.01像素的精度,所以这是不够的。最大纹理大小是有限的,所以我不知道在OpenGL中是否可能