【问题标题】:PyOpenGL Texture_3D and Numpy not renderingPyOpenGL Texture_3D 和 Numpy 不渲染
【发布时间】:2014-06-12 11:15:42
【问题描述】:

我正在尝试进行简单的渲染,将 TIFF 图像中的数据加载到 numpy 矩阵中并制作 3D 纹理。 Tiff 图像是强度图像,我希望将此强度图像重新映射为亮度或 alphacolor 图像。

虽然我认为我了解 GL_Texture_3D 的过程,但运行代码没有错误,但我仍然没有获得视觉结果。我当然在做一些非常错误的简单事情。 谁能帮我理解我的错误?

这是代码的简短版本[已更正]:

编辑 2:尝试正确转换类型: 正如 Reto Koradi 所建议的,我可能面临转换问题。因此,我将 numpy 数组转换为 uint8,确保值与全零不同,并将其传递给 channel_RGBA_buffer uint8 数组。 仍然产生一个黑色的窗口。

编辑 3:使用 Glumpy 方法: 读取 Glumpy 的函数“纹理”(https://code.google.com/p/glumpy/source/browse/glumpy/image/texture.py?r=8cbc2aa2b277c07b59fba964edd327370a8e8091)我将目标 GL 格式 GL_RGBA 更改为 GL_RGBA16,并在调用后添加了 glBindTexture(GL_TEXTURE_3D, 0) glTexImage3D。仍然不确定为什么是 0 而不是纹理。

结果仍然是一个黑色窗口,但是当关闭这个窗口时,我看到数据出现了。好像我要多加一层。

import sys

import numpy
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from OpenGL.arrays import vbo
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GLUT.freeglut import *




class test_TIFF_render:

    def __init__(self):
        self.something = True

    def load_texture(self):

        global texture


        #read file as array, for simplicity I will just make a random numpy 3D matrix 
        tiff_mean = numpy.random.rand(3,300,300)
        tiff_mean = tiff_mean*1000
        tiff_mean = tiff_mean.astype('uint8')

    shape_array = tiff_mean.shape
        shape_array = tiff_mean.shape
        #we have the data now, let's set the texture
        tiff_mean = tiff_mean.reshape(tiff_mean.shape[1]*tiff_mean.shape[2]*tiff_mean.shape[0])
        texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_3D,texture)
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER)
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER)
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_BORDER)
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

        #now we need to convert the intensity data organized in 3D matrix into an RGBA buffer array (pixel1R, pixel1G, pixel1B, pixel1A, pixel2R....)
        channel_RGBA_buffer = numpy.zeros(tiff_mean.shape[0]*4, numpy.uint8)

        for i in range(0,tiff_mean.shape[0]):
            channel_RGBA_buffer[i*4] = tiff_mean[i]     #R
            channel_RGBA_buffer[i*4+1] = tiff_mean[i]   #G
            channel_RGBA_buffer[i*4+2] = tiff_mean[i]   #B
            channel_RGBA_buffer[i*4+3] = tiff_mean[i]   #A
            if numpy.mod(i,100000)==0:
                print('count %d',i)


        glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16, shape_array[1], shape_array[2], shape_array[0], 0, GL_RGBA, GL_UNSIGNED_BYTE, channel_RGBA_buffer)
glBindTexture( GL_TEXTURE_3D, 0 )

    def display(self):

        glClear( GL_COLOR_BUFFER_BIT  | GL_DEPTH_BUFFER_BIT )

        glEnable( GL_ALPHA_TEST )
        glAlphaFunc( GL_GREATER, 0.03)

        glEnable(GL_BLEND)
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )

        glMatrixMode( GL_TEXTURE )
        glLoadIdentity()



        glEnable(GL_TEXTURE_3D);
        glBindTexture( GL_TEXTURE_3D, texture);
        dOrthoSize = 1
        for Indx in self.my_range(-1,1,0.01):
            TexIndex = round(Indx,2)
            glBegin(GL_QUADS)
            glTexCoord3f(0.0, 0.0, (TexIndex+1.0)/2.0)
            glVertex3f(-dOrthoSize,-dOrthoSize,TexIndex)
            glTexCoord3f(1.0, 0.0, (TexIndex+1.0)/2.0)
            glVertex3f(dOrthoSize,-dOrthoSize,TexIndex)
            glTexCoord3f(1.0, 1.0, (TexIndex+1.0)/2.0)
            glVertex3f(dOrthoSize,dOrthoSize,TexIndex)
            glTexCoord3f(0.0, 1.0, (TexIndex+1.0)/2.0)
            glVertex3f(-dOrthoSize,dOrthoSize,TexIndex);
            glEnd()

        glBindTexture( GL_TEXTURE_3D, texture )

    def my_range(self,start, end, step):
        while start <= end:
            yield start
            start += step

glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA)

glutInitWindowSize(300,300)
window = glutCreateWindow(b"I really hope this works")


test111 = test_TIFF_render()
test111.load_texture()

glutDisplayFunc(test111.display)
glutMainLoop()

我正在用 Python3.3 运行 Win7 64 位。

【问题讨论】:

  • 您使用GL_CLAMP_TO_BORDER 的任何原因都没有在任何地方定义边框颜色?您的意思是偶然使用GL_CLAMP_TO_EDGE 吗?
  • 我天真地关注/移植这个例子到 python (codeproject.com/Articles/352270/…)
  • 啊,好吧。这实际上是完全有效的,你可以忽略我的评论 :) 默认边框颜色是 black,因此这将为在范围 [0 之外采样的任何坐标产生黑色纹素,1]。假设空白空间应该是黑色,那么这种行为是可以接受的。 GL_CLAMP_TO_EDGE 会做一些完全不同的事情,它会采用边缘颜色并将其延伸到无穷大。这是对换行模式here 的一个很好的视觉总结(在这种情况下,边框颜色=红色)。
  • 那个总结比一本书的章节更有用。'
  • 但是,我仍然没有渲染。

标签: python opengl python-3.3 pyopengl


【解决方案1】:

我没有使用过 numpy,但是按照我阅读文档的方式 (http://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html),numpy.zeros() 默认会生成一个 float64 值数组。然后将GL_INT 作为glTexImage3D() 的类型参数传递。看起来我们这里的类型不匹配。

用于纹理数据的典型数据类型是无符号字节。所以我认为它应该看起来像这样:

channel_RGBA_buffer = numpy.zeros(tiff_mean.shape[0]*4, numpy.uint8)
...
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, shape_array[1], shape_array[2], shape_array[0], 0,
             GL_RGBA, GL_UNSIGNED_BYTE, channel_RGBA_buffer)

编辑,更新新版本的代码:看起来您知道生成介于 0.0 和 1.0 之间的随机浮点值,将它们转换为字节 (uint8) 值,然后将其用于纹理数据。我相信这将导致您的所有字节值都为 0,或者可能部分为 1,具体取决于舍入的工作方式。但是字节范围的值是0-255。将随机浮点数转换为纹理数据时,您可能需要乘以 255.0:

channel_RGBA_buffer[i*4] = 255.0 * tiff_mean[i]     #R
channel_RGBA_buffer[i*4+1] = 255.0 * tiff_mean[i]   #G
channel_RGBA_buffer[i*4+2] = 255.0 * tiff_mean[i]   #B
channel_RGBA_buffer[i*4+3] = 255.0 * tiff_mean[i]   #A

【讨论】:

  • 虽然我同意这是我的代码中的一个主要缺陷,但肯定还有其他问题,因为这并不能解决问题。它必须是uint8吗?我以为我可以使用int16。我更正了主帖中的代码,但仍然没有结果。
  • 您可以使用 16 位组件的纹理。但是你必须小心你传递给glTexImage3D()的数据格式与format参数相匹配。
  • 我根据您的最新代码更新了答案。坦率地说,我只是一个非常随意的 Python 用户,所以我并不总是确定它如何处理数据类型和转换。
猜你喜欢
  • 2018-09-16
  • 2019-06-26
  • 2014-07-15
  • 2020-10-20
  • 2011-08-23
  • 2021-11-27
  • 1970-01-01
  • 2021-10-12
  • 2021-07-15
相关资源
最近更新 更多