Thread: [PyOpenGL-Users] Problem with numpy arrays and OpenGL textures
Brought to you by:
mcfletch
From: Adeola B. <the...@gm...> - 2008-01-04 19:18:39
|
Hi everyone, I'm doing a project using wxPython and pyopengl, and I seem to have a problem rendering textures. This is code that worked before my hard drive had a meltdown, but not since I re-installed everything. I've determined the problem is in the OpenGL part of my program. I do some calculations to generate a 2D numpy array that holds the image data, and pylab.imshow() shows me the image as it is meant to be. I used the same algorithm in Octave and MATLAB, and all are giving me the right picture. However, using pyOpenGL and the numpyhandler functions (http://cours- info.iut-bm.univ-fcomte.fr/docs/python/OpenGL/ OpenGL.arrays.numpymodule.NumpyHandler-class.html) doesn't seem to work. I get a garbled screen pocked with black pixels. I am including my openGL code below. What am I doing wrong? And yes, I did make the dtype of my array 'float32'. -------code snippets------ import wx from wx.glcanvas import GLCanvas from OpenGL.GLU import * from OpenGL.GL import * from OpenGL.arrays.numpymodule import NumpyHandler PC = 1 RI = 0 class myGLCanvas(GLCanvas): def __init__(self, parent): GLCanvas.__init__(self, parent,-1) wx.EVT_PAINT(self, self.OnPaint) self.init = 0 self.mode = -1 # making a texture for the range image self.texture = glGenTextures(1) # making a spot for the point cloud points self.cloud = None return def OnPaint(self,event): dc = wx.PaintDC(self) self.SetCurrent() if not self.init: self.InitGL() self.init = 1 self.OnDraw() return def OnDraw(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) if self.mode == RI: self.drawRange() elif self.mode == PC: self.drawCloud() def InitGL(self): glClearColor(0.0, 0.0, 0.0, 0.0); glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) glClear(GL_COLOR_BUFFER_BIT) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_PACK_ALIGNMENT, 1) #NTSC colour scales... glPixelTransferf(GL_RED_SCALE, 0.299); glPixelTransferf(GL_GREEN_SCALE, 0.587); glPixelTransferf(GL_BLUE_SCALE, 0.114); glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0,1.0,0,1.0,-1.0,1.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() return def rangeImage(self, image): glBindTexture(GL_TEXTURE_2D, self.texture) glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) # flatten it into a list so the OpenGL calls work n = NumpyHandler() fI = image.flatten() flatImage = n.dataPointer(n.contiguous(fI)) print n.contiguous(fI) gluBuild2DMipmaps(GL_TEXTURE_2D, 1, image.shape[0]+1, image.shape[1]+1, GL_LUMINANCE, GL_FLOAT, flatImage) self.mode = RI self.OnDraw() def drawRange(self): ''' Controls the actual drawing of the range image''' glMatrixMode(GL_MODELVIEW) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glColor3f(1.0,1.0,1.0) glEnable(GL_TEXTURE_2D) glBindTexture(GL_TEXTURE_2D, self.texture) glBegin(GL_TRIANGLE_FAN) glTexCoord2d(1,1); glVertex3f(0.0, 0.0, 0.0) glTexCoord2d(1,0); glVertex3f(0.0, 1.0, 0.0) glTexCoord2d(0,0); glVertex3f(1.0, 1.0, 0.0) glTexCoord2d(0,1); glVertex3f(1.0, 0.0, 0.0) glEnd() self.SwapBuffers() --------end snippet----------- |
From: Mike C. F. <mcf...@vr...> - 2008-01-04 20:56:17
Attachments:
test_context_numpy.py
|
Adeola Bannis wrote: > Hi everyone, > > I'm doing a project using wxPython and pyopengl, and I seem to have a > problem rendering textures. This is code that worked before my hard > drive had a meltdown, but not since I re-installed everything. > > I've determined the problem is in the OpenGL part of my program. I do > some calculations to generate a 2D numpy array that holds the image > data, and pylab.imshow() shows me the image as it is meant to be. I > used the same algorithm in Octave and MATLAB, and all are giving me > the right picture. > > However, using pyOpenGL and the numpyhandler functions (http://cours- > info.iut-bm.univ-fcomte.fr/docs/python/OpenGL/ > OpenGL.arrays.numpymodule.NumpyHandler-class.html) doesn't seem to > work. I get a garbled screen pocked with black pixels. I am including > my openGL code below. What am I doing wrong? > > And yes, I did make the dtype of my array 'float32'. > When I alter your code to actually run (the attached script doesn't seem to do anything) I wind up with a working script. It does point to a bug in the current PyOpenGL 3.0.0b1's handling of void pointer arrays (they are supposed to auto-convert numpy arrays, but I had to explicitly extract a void pointer to make it work). I note that your spec for the image size is wrong, you're adding 1 to the dimensions, which should not be necessary, and could have the effect you described (garbled, with black pixels). I've attached what I'm running, so you can point out what's different. Enjoy, Mike -- ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com |
From: Adeola B. <the...@gm...> - 2008-01-05 19:31:30
|
Thanks Mike, It wasn't so much a script I sent as a class definition. There probably should have been some main function for testing, but I didn't feel like writing up the wxApp. I don't currently have OpenGLContext installed, so I can't (yet) directly run your code. The +1 in the dimensions were necessary in my code before, at least in the horizontal direction - otherwise the image had a characteristic "twist". I had already tried it without them, but with little improvement. If you're interested I've attached the image I get with pylab.imshow() and the image I get on my GLCanvas. I tried the image.ctypes.data_as() conversion, but then my program segfaults whenever it gets to the gluBuild2DMipmaps call. On Jan 4, 2008 3:56 PM, Mike C. Fletcher <mcf...@vr...> wrote: > When I alter your code to actually run (the attached script doesn't seem > to do anything) I wind up with a working script. It does point to a bug > in the current PyOpenGL 3.0.0b1's handling of void pointer arrays (they > are supposed to auto-convert numpy arrays, but I had to explicitly > extract a void pointer to make it work). I note that your spec for the > image size is wrong, you're adding 1 to the dimensions, which should not > be necessary, and could have the effect you described (garbled, with > black pixels). > > I've attached what I'm running, so you can point out what's different. > > Enjoy, > Mike > > -- > ________________________________________________ > Mike C. Fletcher > Designer, VR Plumber, Coder > http://www.vrplumber.com > http://blog.vrplumber.com > > |
From: Mike C. F. <mcf...@vr...> - 2008-01-05 22:03:18
|
Adeola Bannis wrote: > Thanks Mike, > > It wasn't so much a script I sent as a class definition. There > probably should have been some main function for testing, but I didn't > feel like writing up the wxApp. > > I don't currently have OpenGLContext installed, so I can't (yet) > directly run your code. > The +1 in the dimensions were necessary in my code before, at least in > the horizontal direction - otherwise the image had a characteristic > "twist". I had already tried it without them, but with little > improvement. If you're interested I've attached the image I get with > pylab.imshow() and the image I get on my GLCanvas. > > I tried the image.ctypes.data_as() conversion, but then my program > segfaults whenever it gets to the gluBuild2DMipmaps call. > The problem I'm having here is that I can't reproduce your failure, as your code doesn't seem to include the failing code (though as I mentioned, the off-by-one dimensions are suspicious). I've got my float-based image displaying properly with the code I sent you. The most likely sources of segfaulting is that you're passing a non-contiguous array, or you are passing dimensions that are too large. Either one will cause OpenGL to overstep it's array bounds. In your code you are calling contiguous and then throwing away the result IIRC, any chance you intended to use those results? Good luck, Mike -- ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com |
From: Adeola B. <the...@gm...> - 2008-01-08 15:10:25
|
Well, Now I have a recognisable image that just seems to be "twisted funny" (not again...), after I decided to use GL_UNSIGNED_BYTE instead of GL_FLOAT. I think the strange orientation of my picture might just be due to placing the corners in the wrong order or some such. Last time, I resolved the whole "twisted funny" problem with an offset of +/-1. It's also a bit dark, but that's definitely fixable. Here's a picture of the "funny looking" image to compare to the "good" image I sent earlier. Thank you so much for all your help - I think the ctypes call made the difference between rendering gook and rendering the texture. Adeola On Jan 5, 2008 5:03 PM, Mike C. Fletcher <mcf...@vr...> wrote: > Adeola Bannis wrote: > > Thanks Mike, > > > > It wasn't so much a script I sent as a class definition. There > > probably should have been some main function for testing, but I didn't > > feel like writing up the wxApp. > > > > I don't currently have OpenGLContext installed, so I can't (yet) > > directly run your code. > > The +1 in the dimensions were necessary in my code before, at least in > > the horizontal direction - otherwise the image had a characteristic > > "twist". I had already tried it without them, but with little > > improvement. If you're interested I've attached the image I get with > > pylab.imshow() and the image I get on my GLCanvas. > > > > I tried the image.ctypes.data_as() conversion, but then my program > > segfaults whenever it gets to the gluBuild2DMipmaps call. > > > The problem I'm having here is that I can't reproduce your failure, as > your code doesn't seem to include the failing code (though as I > mentioned, the off-by-one dimensions are suspicious). I've got my > float-based image displaying properly with the code I sent you. The > most likely sources of segfaulting is that you're passing a > non-contiguous array, or you are passing dimensions that are too large. > Either one will cause OpenGL to overstep it's array bounds. In your > code you are calling contiguous and then throwing away the result IIRC, > any chance you intended to use those results? > > Good luck, > > Mike > > -- > ________________________________________________ > Mike C. Fletcher > Designer, VR Plumber, Coder > http://www.vrplumber.com > http://blog.vrplumber.com > > |
From: Dirk R. <di...@li...> - 2008-01-08 16:00:46
|
Hi Adeola, Adeola Bannis wrote: > Well, > > Now I have a recognisable image that just seems to be "twisted funny" > (not again...), after I decided to use GL_UNSIGNED_BYTE instead of > GL_FLOAT. I think the strange orientation of my picture might just be > due to placing the corners in the wrong order or some such. Last time, > I resolved the whole "twisted funny" problem with an offset of +/-1. > It's also a bit dark, but that's definitely fixable. Here's a picture > of the "funny looking" image to compare to the "good" image I sent > earlier. > > Thank you so much for all your help - I think the ctypes call made the > difference between rendering gook and rendering the texture. I don't have much experience with PyOpenGL, but I do with OpenGL, so take the following with a grain of salt. The most common reason for 'twisted funny' images is forgetting to set GL_PACK_ALIGNMENT resp. GL_UNPACK_ALIGNMENT to 1 in glPixelStore. By default OpenGL assumes image rows to start on 32-bit aligned addresses, which for RGB byte images is only true if the width is a multiple of 4. Hope it helps Dirk |
From: Neal H. <nh...@do...> - 2008-01-08 20:53:50
|
Hi, I tried to find the answer myself -- I really did -- but now I seem to be at a dead end. This worked in 2.0.1.09.dfsg.1-0.3 on ubuntu feisty: def handleSelect( self, index ): """Handle menu item selection by calling the handler specified in the menu description.""" try: name, fn = self.dispatchTable[index] except: return if callable(fn): fn() def create_menu( self, items ): """Create the open GL menu based on the menu descriptor in 'items'.""" id = glutCreateMenu( self.handleSelect ) ... but not in 3.0.0 on ubutnu gutsy. On that last line ("id = glutCreateMenu...") I get: Traceback (most recent call last): File "./viewframe", line 21, in <module> app = FrameViewer( fd=framedata ) File "../OpenGL/GLFramework.py", line 90, in __init__ self.init_GL() File "../OpenGL/GLFramework.py", line 358, in init_GL m = GLMenu( menu ) File "../OpenGL/GLFramework.py", line 853, in __init__ self.create_menu( items ) File "../OpenGL/GLFramework.py", line 868, in create_menu id = glutCreateMenu( self.handleSelect ) File "/usr/lib/python2.5/site-packages/OpenGL/GLUT/special.py", line 165, in glutCreateMenu result = simple.glutCreateMenu( cCallback ) ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: expected CFunctionType instance instead of CFunctionType ----------------------------------- Some of the other problems I had when searching for solution: 1. In the documentation, http://pyopengl.sourceforge.net/documentation/manual/glutCreateMenu.3GLUT.xml clicking on the Python Sample Code link at the bottom results in a server timeout (cvs.sourceforge...) 2. Ubuntu feisty had the Demo/suit/GLUT.py file, but there was nothing obvious from looking at that (of course, it was on a system whose version worked). 3. Ubuntu gutsy doesan't have that file, nor could I find it in any of the places I looked. Thanks neal -- Neal Holtz http://cee.carleton.ca/~nholtz Dept. of Civil and Environmental Engineering, Carleton University, Ottawa, Ontario, Canada K1S 5B6. nh...@do... |