开发者

Interoperability between OpenCV Python interface and a ctypes library

开发者 https://www.devze.com 2023-03-27 00:49 出处:网络
I\'m using the Python interface from OpenCV 2.3. I have a library written in C that expects, as arguments, OpenCV objects such as IplImage. Like this:

I'm using the Python interface from OpenCV 2.3. I have a library written in C that expects, as arguments, OpenCV objects such as IplImage. Like this:

void MyFunction(IplImage* image);

I wish, from my Python code, to call this function. I've tried:

library.MyFunction(image)

But i开发者_如何学JAVAt gives me an error:

ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1

I've also tried to use byref but it still doesn't works:

TypeError: byref() argument must be a ctypes instance, not 'cv.iplimage'

How do I do this?


cv.iplimage is a CPython object defined by iplimage_t. It wraps the IplImage pointer that you need. There are a few ways to get at this pointer. I'll use the fact that CPython id returns the object base address.

import cv, cv2
from ctypes import *

You could use c_void_p instead of defining IplImage. I define it below in order to demonstrate that the pointer is correct.

class IplROI(Structure):
    pass

class IplTileInfo(Structure):
    pass

class IplImage(Structure):
    pass

IplImage._fields_ = [
    ('nSize', c_int),
    ('ID', c_int),
    ('nChannels', c_int),               
    ('alphaChannel', c_int),
    ('depth', c_int),
    ('colorModel', c_char * 4),
    ('channelSeq', c_char * 4),
    ('dataOrder', c_int),
    ('origin', c_int),
    ('align', c_int),
    ('width', c_int),
    ('height', c_int),
    ('roi', POINTER(IplROI)),
    ('maskROI', POINTER(IplImage)),
    ('imageId', c_void_p),
    ('tileInfo', POINTER(IplTileInfo)),
    ('imageSize', c_int),          
    ('imageData', c_char_p),
    ('widthStep', c_int),
    ('BorderMode', c_int * 4),
    ('BorderConst', c_int * 4),
    ('imageDataOrigin', c_char_p)]

The CPython object:

class iplimage_t(Structure):
    _fields_ = [('ob_refcnt', c_ssize_t),
                ('ob_type',  py_object),
                ('a', POINTER(IplImage)),
                ('data', py_object),
                ('offset', c_size_t)]

Load an example as an iplimage:

data = cv2.imread('lena.jpg')  # 512 x 512
step = data.dtype.itemsize * 3 * data.shape[1]
size = data.shape[1], data.shape[0]
img = cv.CreateImageHeader(size, cv.IPL_DEPTH_8U, 3)
cv.SetData(img, data, step)

In CPython the id of img is its base address. Using ctypes you have direct access to the a field of this object, i.e. the IplImage * that you need.

>>> ipl = iplimage_t.from_address(id(img))
>>> a = ipl.a.contents
>>> a.nChannels
3
>>> a.depth
8
>>> a.colorModel
'RGB'
>>> a.width
512
>>> a.height
512
>>> a.imageSize
786432
0

精彩评论

暂无评论...
验证码 换一张
取 消