[Pyobjc-dev] Again: QTKit CVImageBufferRef - howto access the data
Brought to you by:
ronaldoussoren
|
From: Ulrich E. <li...@ne...> - 2009-06-14 15:45:29
|
Hi there !
i'm still struggling with my QTKit capture module using pyobjc and to
retrieve
actual image data (which should finally end up in a numpy array). i'm
having
trouble to get to the actual data from the CVImageBufferRef.
after the fix from Ronald i'm able to access the CVImageBufferRef as
hinted
in most of the objective-c examples like:
@objc.signature('v@:@{__CVBuffer=@}@@')
def
captureOutput_didOutputVideoFrame_withSampleBuffer_fromConnection_
(self, captureOutput,
videoFrame, sampleBuffer, connection):
videoFrame = videoFrame[0]
#print videoFrame, sampleBuffer
print
sampleBuffer.formatDescription().localizedFormatSummary()
CVPixelBufferRetain(videoFrame)
buffer_to_release = self.current_buffer
self.current_buffer = videoFrame
if buffer_to_release is not None:
CVPixelBufferRelease(buffer_to_release)
print "colorspace:",
CVImageBufferGetColorSpace(self.current_buffer)
print "displaysize",
CVImageBufferGetDisplaySize(self.current_buffer)
print "width:", CVPixelBufferGetWidth(self.current_buffer)
print "height:",
CVPixelBufferGetHeight(self.current_buffer)
print "pixel_format_type:",
CVPixelBufferGetPixelFormatType(self.current_buffer)
print "planar:", CVPixelBufferIsPlanar(self.current_buffer)
#print "extended_pixels:",
CVPixelBufferGetExtendedPixels(self.current_buffer)
print "datasize:",
CVPixelBufferGetDataSize(self.current_buffer)
print "bytes_per_row:",
CVPixelBufferGetBytesPerRow(self.current_buffer)
print "address:",
CVPixelBufferGetBaseAddress(self.current_buffer)
print "attachements:",
CVBufferGetAttachments(self.current_buffer,
kCVAttachmentMode_ShouldPropagate)
#length = CVPixelBufferGetDataSize(self.current_buffer)
ptr = CVPixelBufferGetBaseAddress(self.current_buffer)
at this point i'm able to access the ptr's data using the __getitem__
accessor for each
byte one by one - but this is horribly slow and will not work for my
solution to capture
realtime image streams into numpy arrays for further processing.
the examples suggest to convert the BufferRef to a CIImage but this
statement:
# convert the CVImageBuffer into an NSImage
cimg =
CIImage.alloc().initWithCVImageBuffer_(self.current_buffer)
fails with:
2009-06-14 17:21:43.587 Python[1044:b803] *** Ignoring exception:
<type 'exceptions.ValueError'>: depythonifying 'pointer', got
'CVPixelBufferRef'
which i cannot really interpret nor fix.
i've tried several different ways of passing the ref but none did
something useful.
on the other hand it would be sufficient for me to get real access to
the ptr using ctypes and fill the numpy array directly with the
char buffer using some code like this (works fine for libdc1394
accessed with ctypes):
#func = ctypes.pythonapi.PyBuffer_FromMemory
#func.restype = ctypes.py_object
# XXX howto convert pyobjc varlist to ctypes pointer
#buffer = func(ptr, length)
#ret = numpy.frombuffer( buffer, numpy.uint8 )
#ret = numpy.array(ptr.as_tuple(length))
maybe one of you has a hint how to fix the ValueError or access the
ptr's data directly using ctypes.
any help would be greatly appreciated - i'm fairly stuck now ;-)
thanks!
Ulrich
Am 22.04.2009 um 07:57 schrieb Ulrich Eck:
> Hi Ronald,
>
> thanks for your immediate action/help !!!
>
> i updated pyobjc-svn today and i can access the CVImageBufferRef now
> (still struggling how to use it) but my initial problem is fixed now.
>
> when i have a working example, i'll post it to the list for the
> records.
>
> thanks and have a nice day!
>
> Ulrich
>
> Am 21.04.2009 um 17:05 schrieb Ronald Oussoren:
>
>> Ulrich,
>>
>> The CoreVideo bindings in subversion were incorrect until a moment
>> ago. I've just checked in an updated version of the Quartz bindings
>> (r2166), those fix most of the problems with CoreVideo.
>>
>> That said, I haven't used the CoreVideo bindings in real code yet
>> and there aren't any Python examples using CoreVideo either and this
>> means there may be issues left. Other than creating CVPixel buffers
>> in Python code (CVPixelBufferCreate and friends) the bindings should
>> be complete though.
>>
>> To answer your question:
>>
>> First of all: use "import Quartz" in your module to ensure that the
>> CoreVideo bindings are loaded, otherwise
>> PyObjC won't load the right framework bindings.
>>
>> PyObjC should then automaticly deduce the correct signature for the
>> delegate method, not doing so would be a bug in the QTKit bindings.
>>
>> BTW. Which version of PyObjC are you using?
>>
>> Ronald
>>
>> On 20 Apr, 2009, at 3:23, Ulrich Eck wrote:
>>
>>> hi,
>>>
>>> i spend a couple of days to find out how to do video capturing
>>> using the current pyobc QTKit framework wrappers and run into a
>>> problem...
>>>
>>> i couldn't find out, how to write the signature for the selector of
>>> my delegate for QTCaptureDecompressedVideoOutput
>>> with the following definition:
>>>
>>> - (void)captureOutput:(QTCaptureOutput *)captureOutput
>>> didOutputVideoFrame:(CVImageBufferRef)videoFrame
>>> withSampleBuffer:(QTSampleBuffer *)sampleBuffer
>>> fromConnection:(QTCaptureConnection *)connection
>>>
>>> i tried several signature definitions like:
>>>
>>> @objc.signature('v@:@{__CVBuffer=*}@@')
>>> @objc.signature('v@:@{__CVBuffer=@}@@')
>>> @objc.signature('v@:@^{__CVBuffer=}@@')
>>> @objc.signature('v@:@@@@')
>>>
>>> but they all end up in either a PyObcPointer created warning or a
>>> NSCFType for videoStream, which seems not be usable
>>> at all (can i cast to an CVImageBufferRef somehow ?).
>>>
>>> output example without signature:
>>> PyObjCPointer created: at 0x29f4590 of type {__CVBuffer=}@@
>>> got frame: <QTCaptureDecompressedVideoOutput: 0x2981ac0>
>>> <PyObjCPointer object at 0x25c8b78> <QTSampleBuffer: 0x29f3600>
>>> <QTCaptureConnection: 0x2982510 vide 2vuy>
>>>
>>> output example for the "@objc.signature('v@:@@@@')" signature:
>>> got frame: <QTCaptureDecompressedVideoOutput: 0x2982010> <NSCFType:
>>> 0x29f7310> <QTSampleBuffer: 0x29f5bf0> <QTCaptureConnection:
>>> 0x2982a60 vide 2vuy>
>>>
>>> using "@objc.signature('v@:@{__CVBuffer=}@@')" results in an error
>>> message:
>>> <type 'exceptions.RuntimeError'>: Cannot create FFI CIF: 1
>>>
>>>
>>> now i'm lost ... has anyone here on the list an idea how to convice
>>> the pyobjc wrapper to pass me a valid object/reference to the
>>> CVImageBufferRef or what to do with the NSCFType to get to the
>>> buffer -- as shown in the example below .. i want to extract the
>>> image-data
>>> from the captured video (possibly as string-buffer reference for
>>> further use with numpy+ctypes).
>>>
>>> any help is greatly appreciated !!
>>>
>>> thanks for your help
>>>
>>> cheers Ulrich
>>>
>>>
>>> here is a minimal example of my code (created a simple pyobjc app
>>> in xcode and this is the main app-delegate):
>>> i can also provide the whole example for tests if needed.
>>>
>>>
>>> ############################
>>> from Foundation import *
>>> from AppKit import *
>>> from QTKit import *
>>>
>>> k24RGBPixelFormat = 0x00000018 # 24 bit rgb
>>> k32ARGBPixelFormat = 0x00000020 # 32 bit argb (Mac)
>>>
>>> class qtkit_captureAppDelegate(NSObject):
>>> def applicationDidFinishLaunching_(self, sender):
>>> NSLog("Application did finish launching.")
>>>
>>>
>>> session = QTCaptureSession.alloc().init()
>>>
>>> device =
>>> QTCaptureDevice.defaultInputDeviceWithMediaType_(QTMediaTypeVideo)
>>> if device is None:
>>> print "failed to open device."
>>> return
>>>
>>> device.open_(None)
>>>
>>> input = QTCaptureDeviceInput.alloc().initWithDevice_(device)
>>> session.addInput_error_(input, None)
>>>
>>> output = QTCaptureDecompressedVideoOutput.alloc().init()
>>>
>>> settings = dict(kCVPixelBufferWidthKey=640.0,
>>> kCVPixelBufferHeightKey=480.0,
>>>
>>> kCVPixelBufferPixelFormatTypeKey=k32ARGBPixelFormat,
>>> )
>>>
>>> output.setPixelBufferAttributes_(settings)
>>> session.addOutput_error_(output, None)
>>>
>>> class logger(NSObject):
>>>
>>> current_buffer = None
>>>
>>> # Declaration:
>>> #- (void)captureOutput:(QTCaptureOutput *)captureOutput
>>> didOutputVideoFrame:(CVImageBufferRef)videoFrame
>>> # withSampleBuffer:(QTSampleBuffer *)sampleBuffer
>>> fromConnection:(QTCaptureConnection *)connection
>>>
>>> #@objc.signature('v@:@{__CVBuffer=*}@@')
>>> #@objc.signature('v@:@{__CVBuffer=@}@@')
>>> #@objc.signature('v@:@^{__CVBuffer=}@@')
>>> @objc.signature('v@:@@@@')
>>> def
>>> captureOutput_didOutputVideoFrame_withSampleBuffer_fromConnection_
>>> (self, captureOutput, videoFrame, sampleBuffer, connection):
>>> NSLog("got frame: %s %s %s %s" % (captureOutput,
>>> videoFrame, sampleBuffer, connection))
>>>
>>> # always have only one frame retained
>>> #CVBufferRetain(videoFrame)
>>> #buffer_to_release = self.current_buffer
>>> #self.current_buffer = videoFrame
>>> #if buffer_to_release is not None:
>>> # CVBufferRelease(buffer_to_release)
>>>
>>> # convert the CVImageBuffer into an NSImage
>>> #cimg = CIImage.initWithCVImageBuffer_(test)
>>> #rep = NSCIImageRep.initWithCIImage_(cimg)
>>> #nimg = NSImage.alloc().initWithSize_(rep.size())
>>> #nimg.addRepresentation_(rep)
>>>
>>>
>>> cb = logger.alloc().init()
>>> output.setDelegate_(cb)
>>> session.startRunning()
>>>
>>> self._data = (session, device, input, output, cb)
>>>
>>> ############################
>>>
>>> ------------------------------------------------------------------------------
>>> Stay on top of everything new and different, both inside and
>>> around Java (TM) technology - register by April 22, and save
>>> $200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
>>> 300 plus technical and hands-on sessions. Register today.
>>> Use priority code J9JMT32. http://p.sf.net/sfu/p_______________________________________________
>>> Pyobjc-dev mailing list
>>> Pyo...@li...
>>> https://lists.sourceforge.net/lists/listinfo/pyobjc-dev
>>
>
>
> ------------------------------------------------------------------------------
> Stay on top of everything new and different, both inside and
> around Java (TM) technology - register by April 22, and save
> $200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
> 300 plus technical and hands-on sessions. Register today.
> Use priority code J9JMT32. http://p.sf.net/sfu/p
> _______________________________________________
> Pyobjc-dev mailing list
> Pyo...@li...
> https://lists.sourceforge.net/lists/listinfo/pyobjc-dev
|