2013-08-06 141 views
1

我想创建一个PyOpenGL/QtOpenGL插件,让我想象任意NumPy的3D矩阵,并不像预想的“立方体魔方”,而不是“方以下顿图的平方“:可视化三维NumPy的阵列PyOpenGL

我有虽然有点的一个粗略的时间用OpenGL。这里是我的代码迄今:是

from OpenGL.GL import * 
from OpenGL.GLUT import * 
from PyQt4 import QtGui, QtOpenGL 
import numpy as np 

action_keymap = { 
    # 'a': lambda: glTranslate(-1, 0, 0), 
    # 'd': lambda: glTranslate(1, 0, 0), 
    # 'w': lambda: glTranslate(0, 1, 0), 
    # 's': lambda: glTranslate(0,-1, 0), 

    'a': lambda: glRotate(-5, 0, 1, 0), 
    'd': lambda: glRotate(5, 0, 1, 0), 
    # 'W': lambda: glRotate(-5, 1, 0, 0), 
    # 'S': lambda: glRotate(5, 1, 0, 0), 
} 

ARRAY = np.ones([3,3,3]) 

class GLWidget(QtOpenGL.QGLWidget): 

    def paintGL(self): 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 

    for idx, value in np.ndenumerate(ARRAY): 
     rel_pos = np.array(idx)/np.max(ARRAY.shape) 
     glTranslate(* rel_pos) 
     glutSolidCube(0.9/np.max(ARRAY.shape)) 
     glTranslate(*-rel_pos) 

    def resizeGL(self, w, h): 
    glLoadIdentity() 
    glRotate(35,1,0,0) 
    glRotate(45,0,1,0) 

    def initializeGL(self): 
    glClearColor(0.1, 0.1, 0.3, 1.0) 

    def keyPressEvent(self, event): 
    action = action_keymap.get(str(event.text())) 
    if action: 
     action() 
    self.updateGL() 

    def mousePressEvent(self, event): 
    super().mousePressEvent(event) 
    self.press_point = event.pos() 

    def mouseMoveEvent(self, event): 
    super().mouseMoveEvent(event) 
    motion = event.pos()-self.press_point 
    self.press_point = event.pos() 
    glRotate(motion.x(),0,1,0) 
    glRotate(motion.y(),1,0,0) 
    self.updateGL() 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 

    w = GLWidget() 
    w.show() 

    sys.exit(app.exec_()) 

我的问题如下:

1)照明。我一直在阅读照明和材料,但我似乎无法在某个地方获得简单的光线,使其形状更加清晰。我希望最简单,最基本的可能光线能够区分正方形,而不是全部都呈现为纯白色。我知道如何改变颜色,但并不能缓解问题。 我可以在这个格子上发现最简单的光线,以获得子部件的一些清晰度?

2)是缓慢的。我会计算出数学来实现正确定位和调整方格的大小,但是我想知道是否有一种方法可以将流程矢量化(毕竟,它只是将索引转换为平移并将其值转换为立方体数组中每个元素的大小)。我是否应该在cpp中编写扩展,用ctypes包装我的代码,还是有办法将工作外包给OpenGL? 从Python发送重复任务到OpenGL的标准方式是什么?

+0

海事组织这将很难得到像这样的可视化工作。与二维正方形的二维网格不同,三维立方体的三维网格总是会受到遮挡的影响,无论是在可见性还是照明方面。想出一种将你的3d数据“推”到2d格式的方式可能会更容易 - 例如,通过创建一个Hinton图表,也可以以某种方式指示每个单元格的min/max/mean/std等。听起来像是一个非常有趣的可视化问题,但祝你好运! – lmjohns3

+0

是的,我意识到,特别是对于大型矩阵,内部的任何内容都不会从外部看到(我解释术语“遮挡”是错误的吗?)。我打算允许用户“放大”,并使外面的块不可见。 现在我所需要的是能够一眼看出任意数组中有多少个单元格。我会很高兴用线条标记细分的线框立方体。 – RodericDay

+0

我不是OpenGL专家,所以即使我已经在某些有限的情况下设置了灯光,但我无法解释如何去做。一个建议:用'glutWireCube'替换'glutSolidCube'? – lmjohns3

回答

0

这不会直接创建您要查找的可视化类型,但我强烈建议看看Nicholas Rougier提供的glumpy包:https://code.google.com/p/glumpy/。 OpenGL可能会很痛苦,特别是对于不是图形专家的人来说,并且glumpy会将大部分的痛苦抽象出来,让您只在屏幕上显示numpy阵列。

+0

这看起来很有趣。行*数组的dtype必须是numpy.uint8或numpy.float32中的一个(因为在OpenGL纹理数据类型上存在限制),并且数组的形状必须是M,MxN或MxNx中的一个[1,2,3 ,4]。*但是,由于我想使用MxNxK数组,我担心了一点。再次,他在着陆页上有一个很酷的立方体,所以也许它会起作用。 我会研究它。 – RodericDay

+0

是的。尽管我们可以在3D中看到,但我们实际上只在2D中消耗可视化效果。无论如何,你将需要将你的数据映射到某种2D表面 - 毕竟,它最终会显示在2D屏幕上!这里的一个具体想法是设置一个'glumpy.Image'来显示你的3D数组,但一次只显示一个2D数据片。然后,您可以附加滚轮或键盘事件,让用户更改显示的切片。根据我的经验,这样的事情会非常快,但它会显示为一个色彩表而不是立方体。 – lmjohns3

+0

感谢您的帮助。无论哪种方式解决此问题,我都会向您发送消息。 – RodericDay