2011-08-09 11 views
1

OpenCV 2.3のPythonインターフェイスを使用しています。私はIplImageのようなOpenCVオブジェクトを引数として期待するC言語で書かれたライブラリを持っています。このように:OpenCV Pythonインターフェイスとctypesライブラリの相互運用性

void MyFunction(IplImage* image); 

私のPythonコードから、この関数を呼び出すことを望みます。

library.MyFunction(image) 

をしかし、それは私にエラーを与える:私が試した

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

私もbyrefを使用しようとしましたが、それはまだ動作しません:

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

方法私はこれをするのですか?

答えて

2

cv.iplimageは、iplimage_tで定義されたCPythonオブジェクトです。必要なポインタIplImageをラップします。このポインタを取得する方法はいくつかあります。 CPython idがオブジェクトのベースアドレスを返すという事実を使用します。

import cv, cv2 
from ctypes import * 

あなたはIplImageを定義c_void_pの代わりに使用することができます。私は、ポインタが正しいことを示すために以下で定義します。

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)] 

CPythonのオブジェクト:

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

ロードiplimage例としては:CPythonので

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) 

imgidは、そのベース・アドレスです。 ctypesを使用すると、このオブジェクトのaフィールドに直接アクセスできます。つまり、必要なのはIplImage *です。

>>> 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

Ubuntu 14.04のcv2では、イメージはCスタイルのIplImageとして返されません。これはnumpy.ndarray()として返されます。 my_array.data_as(c_void_p)を使用すると、ndarray()値をC関数に渡すのは比較的簡単です。 –