Passing an image pointer to a DLL function in pyth

2019-08-17 15:21发布

问题:

I have a camera that has its own DLL library for passing parameters to the camera, and taking images. I am trying to make calls with this DLL library through python. I need to make a pointer for the raw image data, and i'm not exactly sure how to do this. The DLL has a function name and takes those parameters as inputs:

StTrg_TakeRawSnapShot(hCamera, pbyteraw, dwBufferSize, dwNumberOfByteTrans, dwFrameNo, dwMilliseconds)

hCamera:
    This parameter sets the camera control handle that obtains by StTrg_Open. 

pbyteRaw:
    This parameter sets pointer of the raw image. 

dwBufferSize:
    This parameter sets the buffer size. 

pdwNumberOfByteTrans:
    This parameter sets the pointer that obtains the total number of the bytes of the image. 

pdwFrameNo:
    This parameter sets the pointer that obtains the frame number of the image that counts in the camera.
    This number can be use for the frame drop detection. 

dwMilliseconds:
    This parameter sets the timeout time (Unit is msecond). 

exactly as stated from the documentation of the camera, pbyteraw is: "This parameter sets pointer of the raw image" and that's all the detail they provide.

how do i create this raw image pointer, and then read it to a 2D array that i can work with in python? The camera is black and white, so i am hoping to get a 2D array of values between 0 and 255.

from ctypes import *
import numpy as np

mydll = windll.LoadLibrary('StTrgApi.dll')
hCamera = mydll.StTrg_Open()


im_height = 1600
im_width = 1200
dwBufferSize = im_height * im_width

pbyteraw = (c_ubyte * dwBufferSize)()

dwNumberOfByteTrans = 0

dwFrameNo = 0

dwMilliseconds = 3000

mydll.StTrg_TakeRawSnapShot(hCamera, pbyteraw, dwBufferSize, 
dwNumberOfByteTrans, dwFrameNo, dwMilliseconds)


b_pbyte = bytearray(pbyteraw)

回答1:

With some minor changes, what you have should work. Setting the .argtypes of the function will help catch errors, and if you make instances of the output parameters, you can pass them by reference:

dwNumberOfByteTrans = c_uint32()
dwFrameNo = c_uint32()
mydll.StTrg_TakeRawSnapShot.argtypes = c_void_p,POINTER(c_ubyte),c_uint32,POINTER(c_uint32),POINTER(c_uint32),c_uint32
mydll.StTrg_TakeRawSnapShot(hCamera, pbyteraw, dwBufferSize, byref(dwNumberOfByteTrans), byref(dwFrameNo), dwMilliseconds)

Your raw buffer is a 1D byte array. You can do the math to access the right row/col, or use the ctypes interface numpy provides as @Ross mentioned to provide a more intuitive interface.



回答2:

Since you're working with numpy you can take advantage of the fact that numpy arrays provide a ctypes interface that let you get a reference to the underlying data buffer, which would be suitable to pass to your DLL's function. As long as you're happy keeping your data in a numpy array, try something like the following.

Instead of a ctypes array

pbyteraw = (c_ubyte * dwBufferSize)()

use a numpy array:

pbyteraw = np.zeros((im_height, im_width), dtype=np.uint16)

Then pass a reference to pbyteraw when calling StTrg_TakeRawSnapShot, as follows:

mydll.StTrg_TakeRawSnapShot(hCamera,
                            pbyteraw.ctypes.data_as(POINTER(c_int16)),
                            dwBufferSize*2, dwNumberOfByteTrans,
                            dwFrameNo, dwMilliseconds)

It's not clear what the size and format of the underlying pixels in the buffer are supposed to be though. For example, does the camera return 16-bit grayscale pixels? Big or little endian? You'll need to make sure that the numpy dtype agrees with the data_as ctype.