As an answer to my own question (https://discourse.panda3d.org/viewtopic.php?t=8404 ) here is how you can load and display 2D DICOM images in Panda 3D
Regards,
Reza Alemi
'''
Created on 2010-02-14
@author: Rex Alemi
Demonstration of loading a dicom image as a texture on a surface.
dicom file is read using pydicom (http://code.google.com/p/pydicom/)
and then it is fed to a 2D texture object after selecting the
luminance mode and calculating the gray level according to
window/level settings. key presses are defined to give the user
the ability to dynamically change the window/level setting.
'''
import direct.directbase.DirectStart
from panda3d.core import Texture
from panda3d.core import PTAUchar
from direct.showbase.DirectObject import DirectObject
from direct.gui.OnscreenText import OnscreenText
from direct.task.Task import Task
from panda3d.core import TextNode
import sys
import dicom
import array
class DicomPic(DirectObject):
'''
DicomPic a representaion for a dicom picture
A dicom picture file, as specified by the parameter passed to the class
constructor, is loaded to a plane and showed in front of the camera.
expects pydicom to be initialised.
'''
window = 900
level=100
maxgray=255 #maximum levels of gray available.
basepath = "../models/plane"
minwindow=10
minlevel=50
def __init__(self, filename):
'''
Constructor: Setup and file load
The constructor loads the dicom file and sets up the texture structure
and scene graph. it also installs the key listeners to implement
interactive window/level functionality.
'''
self.escapeEventText = OnscreenText(text="ESC: Quit, a/s: increase/decrease Window, k/l: decrease/increase Level", style=1,
fg=(1,1,1,1), pos=(-1.3, 0.95),
align=TextNode.ALeft, scale = .05)
base.setBackgroundColor(0, 0, 0) #Set the background color
#Set up the key input
self.accept('escape', sys.exit) #Escape quits
self.accept('a',self.incwindow)
self.accept('s',self.decwindow)
self.accept('k',self.declevel)
self.accept('l',self.inclevel)
self.dicompic=dicom.read_file(filename)
self.width=self.dicompic.Rows
self.height=self.dicompic.Columns
self.buffer=array.array('H', self.dicompic.PixelData)
self.window=900
self.level=100
self.maxgray=255
dp=self.dicompic
text= str(dp.StudyDate) + ' ' + str(dp.StudyTime) + ' ' + str(dp.PatientID) + ":" + str(dp[0x10,0x40].value) + str(dp[0x10,0x1010].value)
self.title = OnscreenText(text= text,
style=1, fg=(1,1,1,1), pos=(0.7,-0.95),
scale = .07, mayChange=True)
self.orientPlane = loader.loadModel('../models/plane') #Load the object#load the texture
self.orientTex=Texture.Texture()
self.orientTex.setup2dTexture(self.width,self.height,Texture.TUnsignedByte,Texture.FLuminance)
self.setToGray()
self.orientPlane.setTexture(self.orientTex, 1) #Set the texture
self.orientPlane.reparentTo(render) #Parent to render
self.orientPlane.setPosHprScale(0, 11, -0.8, 0, 0, 180, 7, 7, 7)
self.expTask=taskMgr.add(self.dummytask,"Dummy")
self.expTask.fps=30
def dummytask(self,task):
return Task.cont
def incwindow(self,step=100):
self.window +=step;
if self.window > 65535-self.level: self.window = 65535-self.level
self.setToGray()
def decwindow(self,step=100):
self.window -= step;
if self.window < self.minwindow : self.window = self.minwindow
self.setToGray()
def inclevel(self,step=50):
self.level +=step;
if self.level > 65535-self.window: self.level = 65535-self.window
self.setToGray()
def declevel(self,step=50):
self.level -= step;
if self.level < self.minlevel : self.level = self.minlevel
self.setToGray()
def setToGray(self):
self.pta=self.orientTex.makeRamImage()
self.setWL()
def setWL(self):
'''
setWL() sets visible spectrum according to window and level
expects the window, level, buffer and pta to be initialised.
'''
print 'window '
print self.window
print 'level'
print self.level
for n in range (0,len(self.buffer)):
it = self.buffer[n]
if it < self.level : it=0
elif it > self.level + self.window: it=self.maxgray
else: it=(self.maxgray *(it-self.level))/self.window
self.pta[n]=it
w= DicomPic("../assets/brain_001.dcm")
run()
[/url]
[/code]