[Numpy-discussion] is there a faster way to get a buffer interface than ndarray.tostring()?

Andrew Straw strawman at astraw.com
Wed Feb 25 01:22:05 EST 2009


Given what you're doing, may I also suggest having a look at
http://code.astraw.com/projects/motmot/wxglvideo.html

-Andrew

Chris Colbert wrote:
> As an update for any future googlers: 
> 
> the problem was with revpixels = pixeldata[::-1,:,;:-1] which apparently
> returns an array that is discontinuous in memory. What Lisandro
> suggested worked. pixeldata[::-1,:,;:-1].copy() returns a continuous
> array object which natively implements a single-segment buffer
> interface. i.e. no buffer(revpixels) is needed; just simply revpixels. 
> 
> array.copy() is also 50% faster than array.tostring() on my machine. 
> 
> Chris
> 
> On Tue, Feb 24, 2009 at 9:27 PM, Chris Colbert <sccolbert at gmail.com
> <mailto:sccolbert at gmail.com>> wrote:
> 
>     thanks for both answers! 
> 
> 
>     Lisandro, you're right, I should have declared the array outside the
>     loop. Thanks for catching that!
> 
>     Robert, as always, thanks for the answer. Quick and to the point!
>     You've helped me more than once on the enthought list :)
> 
> 
> 
>     On Tue, Feb 24, 2009 at 8:06 PM, Lisandro Dalcin <dalcinl at gmail.com
>     <mailto:dalcinl at gmail.com>> wrote:
> 
>         When you do pixeldata[::-1,:,::-1], you just got a new array with
>         different strides, but now non-contiguous... So I believe you really
>         need a fresh copy of the data... tostring() copies, but could be
>         slow... try to use
> 
>         revpixels = pixeldata[::-1,:,::-1].copy()
> 
>         ...
> 
>         rgbBMP = wx.BitmapFromBuffer(640, 480, buffer(revpixels))
> 
> 
>         Perhaps you could optimize this by declaring revpixels outside de
>         loop, and then inside de loop doing
> 
>         revpixels[...] = pixeldata[::-1,:,::-1]
> 
> 
>         This way you will save the mem allocation of revpixels at each
>         step of the loop.
> 
> 
> 
> 
> 
>         On Tue, Feb 24, 2009 at 9:15 PM, Chris Colbert
>         <sccolbert at gmail.com <mailto:sccolbert at gmail.com>> wrote:
>         > Hi all,
>         >
>         >  I'm new to mailing list and relatively new (~1 year) to
>         python/numpy. I
>         > would appreciate any insight any of you may have here. The
>         last 8 hours of
>         > digging through the docs has left me, finally, stuck.
>         >
>         > I am making a wxPython program that includes webcam
>         functionality. The
>         > script below just brings up a simple display window that shows
>         the webcam
>         > feed. The problem I am running into is in the
>         WebCamWorker.run() method.
>         > This method reads the raw pixel data (in string form) from the
>         webcam
>         > buffer. This data (thank you microsoft!) comes in BGR and
>         bottom-to-top. I
>         > feed this buffer to the array constructor and then swap the
>         pixel order to
>         > RGB and top-to-bottom. This all happens very fast, ~1ms on a
>         Quad Core, and
>         > the majority of that time is spent constructing the array (the
>         numpy pixel
>         > swapping is on the order of E-5s !). The tostring() method,
>         however, takes a
>         > whopping 10ms to execute. Unfortunately, the
>         wx.BitmapFromBuffer needs a
>         > single segment buffer interface as an argument. Is there a way
>         to expose my
>         > numpy array as a buffer to cut down on this conversion time?
>         >
>         > I have tried sending the array to the PIL Image.fromarray(),
>         but that
>         > eventually requires me to do a Image.tostring() anyway, which
>         negates any
>         > benefit.
>         >
>         > Thanks in advance for the help!
>         >
>         > S. Chris Colbert
>         > Rehabilitation Robotics Laboratory
>         > University of South Florida
>         >
>         >
>         > ####  Code #######
>         >
>         > import VideoCapture
>         > import wx
>         > import time
>         > import threading
>         > import numpy as np
>         > import Image
>         >
>         >
>         > class WebCamWorker(threading.Thread):
>         >     _abort = 0
>         >
>         >     def __init__(self, parent):
>         >         super(WebCamWorker, self).__init__()
>         >
>         >         self._parent = parent
>         >         self.panel = wx.Panel(parent)
>         >
>         >     def run(self):
>         >
>         >         while not self._abort:
>         >
>         >             #numpy arrays reverse pixel data that comes in
>         from CCD as BGR
>         > and bottom to top
>         >
>         >             pixeldata = np.ndarray((480,640,3),
>         > buffer=webcam.getBuffer()[0], dtype='u1')
>         >             revpixels = pixeldata[::-1,:,::-1].tostring()     
>         #tostring is
>         > an order of magnitude slower than the entire array
>         manipulation. need a
>         > faster method.
>         >
>         >             rgbBMP = wx.BitmapFromBuffer(640, 480, revpixels)
>         >             dc = wx.ClientDC(self.panel)
>         >             dc.DrawBitmap(rgbBMP, 0, 0)
>         >             #b = time.clock()
>         >             #print b-a
>         >             time.sleep(0.015)
>         >
>         >
>         >         return
>         >
>         >
>         >
>         > class TestWxWebCam(wx.Frame):
>         >     def __init__(self, parent):
>         >         wx.Frame.__init__(self, parent, -1, size=(640,480))
>         >
>         >         self.worker = WebCamWorker(self)
>         >         self.worker.start()
>         >
>         >
>         >
>         > class TestApp(wx.App):
>         >     def OnInit(self):
>         >         self.frame = TestWxWebCam(None)
>         >         self.frame.Show()
>         >
>         >         return True
>         >
>         >     def OnExit(self):
>         >         WebCamWorker._abort = 1 #this is a hack
>         >
>         >
>         > if __name__ == '__main__':
>         >     webcam = VideoCapture.Device()
>         >     webcam.setResolution(640, 480)
>         >     webcam.displayCapturePinProperties()
>         >     app = TestApp()
>         >     app.MainLoop()
>         >     del webcam
>         >
>         >
>         > ### /Code ######
>         >
>         > _______________________________________________
>         > Numpy-discussion mailing list
>         > Numpy-discussion at scipy.org <mailto:Numpy-discussion at scipy.org>
>         > http://projects.scipy.org/mailman/listinfo/numpy-discussion
>         >
>         >
> 
> 
> 
>         --
>         Lisandro Dalcín
>         ---------------
>         Centro Internacional de Métodos Computacionales en Ingeniería
>         (CIMEC)
>         Instituto de Desarrollo Tecnológico para la Industria Química
>         (INTEC)
>         Consejo Nacional de Investigaciones Científicas y Técnicas (CONICET)
>         PTLC - Güemes 3450, (3000) Santa Fe, Argentina
>         Tel/Fax: +54-(0)342-451.1594
>         _______________________________________________
>         Numpy-discussion mailing list
>         Numpy-discussion at scipy.org <mailto:Numpy-discussion at scipy.org>
>         http://projects.scipy.org/mailman/listinfo/numpy-discussion
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Numpy-discussion mailing list
> Numpy-discussion at scipy.org
> http://projects.scipy.org/mailman/listinfo/numpy-discussion




More information about the NumPy-Discussion mailing list