2013-08-06 142 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