Create image in Python from C pointer (openCV Mat return from C DLL)

asked 2018-08-21 05:07:40 -0500

MathieuG gravatar image

updated 2018-08-21 05:08:31 -0500

Without giving you all details (DLL, wrapper C and code C++), I am using the OpenCV library in my DLL to perform some operations on images. For now, I am using four methods of this library : threshold, adaptivethreshold, filter2D and GaussianBlur. In Python I succeeded to recreate image from the function which return the result of the threshold method but from the other I have some shifts (different for each methods and different values of the same parameter on the same method). My DLL return an unsigned short * pointer because I deal with uint8/16 images.

Moreover, if I call these functions using the different OpenCV methods from a C++ program, I get a correct image without shift.

For example, on Python, I recreate the image from the pointer return by the filter2D function using :

# Load the DLL in memory
mydll = cdll.LoadLibrary("PathOfMyDll.dll")

# Create the (wrapper) class and define all functions which will be available in Python after
# See the header file of the DLL to have the declaration of all functions available
class ImageProcessingDll(object):
    def __init__(self):
        mydll.imSmooth.argtypes = [c_void_p, c_void_p, c_int, c_int, c_int, c_int, c_int]
        mydll.imSmooth.restype = POINTER(c_ushort)

        self.obj = mydll.AllocateHandleImg()

    def imSmooth(self, ptrImg, width, height, inputType, kernelWidth, kernelHeight):
       return mydll.imSmooth(self.obj, ptrImg, width, height, inputType, kernelWidth, kernelHeight)

# Then call this function
handle = ImageProcessingDll();
ptrImg = handle.imSmooth(someImage.__array_interface['data'][0], someImage.width, someImage.height, someImage.type, 2, 2)

# Create image from pointer received by the DLL
numpy.ctypeslib.as_array(cast(ptrImg, POINTER(c_uint16)), shape=(self.img.shape)).copy()

And in C++ I have:

unsigned short * myClass::imSmooth(void *ptrImg, int width, int height, int inputType, int kernelWidth, int kernelHeight)
{
    // imgResult (Mat object) is a class Variable so the result is not temporary and freed at the end of the function call

    // Get image and reshape it as Mat object
    Mat imgTemp = Mat(height, width, inputType, (uchar*)ptrImg).clone();

    // Convert if needed
    if (inputType < 5)
        imgTemp.convertTo(imgTemp, CV_32FC1);
    imgResult = imgTemp.clone();

    // Create kernel (normalized matrix)
    Mat kernel = Mat(kernelHeight, kernelWidth, CV_32FC1, 1) / (float)(kernelWidth*kernelHeight);

    // Process filter with my own kernel
    filter2D(imgTemp, imgResult, -1, kernel, Point(-1, -1), (0, 0), BORDER_DEFAULT);

    // Convert to initial type if needed
    if (imgResult.type() != inputType)
        imgResult.convertTo(imgResult, inputType);

    // Return result
    return imgResult.ptr<ushort>();
}

Let's see the images without and with shift:

C++ image Python image

I don't know if it comes from my way to recreate an image from a pointer on Python, or maybe some OpenCV function rearrange data and so my Python function works correctly but with data in a different order than usual.

Thank you in advance for any advice/help.

edit retag flag offensive close merge delete