2010-10-10 18 views
2

J'essaie d'utiliser OpenCV sur Python 3.1 via ctypes, mais je ne sais pas comment représenter les pointeurs. Par exemple, si je veux charger une image et imprimer le contenu de son premier pixel, je vais écrire en C++:Pointeur sur ctypes pour utiliser OpenCV sur Python 3.1

#include <opencv/cv.h> 
#include <opencv/highgui.h> 

using namespace std; 

int main() { 
    IplImage *img; 
    img = cvLoadImage("/home/foo/foo.png"); 
    CvScalar pixel = cvGet2D(img, 20, 30); 
    printf(pixel) 
    return 0 
} 

Mais en Python, sur ctypes, je dois représenter IplImage, structures CvScalar et plus, et je doit utiliser "pointeurs", pour ce faire, par exemple: IplImage *img;.

Mais comment? J'ai essayé:

from ctypes import * 

cv = cdll.LoadLibrary("libcv.so") 
highgui = cdll.LoadLibrary("libhighgui.so") 

class IplRoi(Structure): 
    _fields_ = [("coi", c_int), 
       ("height", c_int), 
       ("ptr", c_char_p), 
       ("width", c_int), 
       ("xOffset", c_int), 
       ("yOffset", c_int)] 

class IplImage(Structure): 
    _fields_ = [("nChannels", c_int), 
       ("depth", c_int), 
       ("width", c_int), 
       ("height", c_int), 
       ("imageData", c_char_p), 
       ("dataOrder", c_int), 
       ("origin", c_int), 
       ("widthStep", c_int), 
       ("imageSize", c_int), 
       (IplRoi(), c_char_p), 
       ("imageDataOrigin", c_char_p), 
       ("align", c_int)] 

image = IplImage(highgui.cvLoadImage("/home/michael/connerie.jpg")) 
image = byref(image) 
cv.cvGet2D(image, 1, 1) 

Mais je n'ai pas la structure de CvScalar (je ne Kown comment représenter), et je me sers de mauvais pointeurs ctypes, et j'ai une erreur « segfault ».

Répondre

0

Dans OpenCV 2.3, la structure CvScalar est un double[4] enveloppé dans une struct, et les autres définitions de structure montrées dans la question sont significativement différentes. En outre, cvLoadImage a un argument iscolor avec une valeur par défaut en C++. Cela doit être défini sur l'une des constantes CV_LOAD_IMAGE_* lorsqu'il est appelé avec ctypes.

from ctypes import * 

CV_LOAD_IMAGE_UNCHANGED = -1 
CV_LOAD_IMAGE_GRAYSCALE = 0 
CV_LOAD_IMAGE_COLOR = 1 
CV_LOAD_IMAGE_ANYDEPTH = 2 
CV_LOAD_IMAGE_ANYCOLOR = 4 

CvArr = None 

class CvScalar(Structure): 
    _fields_ = [('val', c_double * 4)] # e.g BGRA, see channelSeq 

class IplRoi(Structure): 
    _fields_ = [ 
     ('coi', c_int), 
     ('xOffset', c_int), 
     ('yOffset', c_int), 
     ('width', c_int), 
     ('height', c_int), 
    ] 

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', c_void_p), 
     ('imageSize', c_int), 
     ('imageData', POINTER(c_char)), 
     ('widthStep', c_int), 
     ('BorderMode', c_int * 4), 
     ('BorderConst', c_int * 4), 
     ('imageDataOrigin', POINTER(c_char)), 
    ] 

Pour les tests, je les utilise OpenCV 2.3 libs dans le Debian repository et les 4 canaux suivants PNG:

rgba8_trans.png

cv = CDLL('libopencv_core.so.2.3') 
highgui = CDLL('libopencv_highgui.so.2.3') 

highgui.cvLoadImage.restype = POINTER(IplImage) 
highgui.cvLoadImage.argtypes = [c_char_p, c_int] 

cv.cvGet2D.restype = CvScalar 
cv.cvGet2D.argtypes = [POINTER(CvArr), c_int, c_int] 

pimg = highgui.cvLoadImage(
    b'data/rgba8_trans.png', CV_LOAD_IMAGE_UNCHANGED) 
pixsc = cv.cvGet2D(pimg, 30, 30) 

img = pimg[0] 
pix = tuple(pixsc.val) 
print('width = %d, height = %d\n' % (img.width, img.height)) 
print('y=30, x=30') 
print(*zip(img.channelSeq.decode(), pix)) 

Sortie:

width = 85, height = 62 

y=30, x=30 
('B', 128.0) ('G', 128.0) ('R', 64.0) ('A', 176.0)