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

asked 2018-08-10 07:42:14 -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 :

# Definition of the function on the Python wrapper
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)

# Call function
ptrImg = 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

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

Comments

all problems with it stem from yuor custom, selfmade python wrappers

berak gravatar imageberak ( 2018-08-10 10:15:32 -0500 )edit

What do you mean ?

MathieuG gravatar imageMathieuG ( 2018-08-10 15:11:21 -0500 )edit

For information the code posted is a part of the real code. In real, I create a wrapper in Python as a class and each function of my DLL is a method of this class. I just add to my post the part where I initialize the wrapper to show you the type of data I set.

MathieuG gravatar imageMathieuG ( 2018-08-13 02:47:30 -0500 )edit

your c++ function returns a pointer to local data, that's undefined behaviour. (it is no more valid, after leaving the function)

berak gravatar imageberak ( 2018-08-13 03:17:36 -0500 )edit

also, your imgResult is float (CV_32F), not ushort.

imho, your design is entirely broken here. why do you need to interface c++ and python in this way, even ?

berak gravatar imageberak ( 2018-08-13 03:33:26 -0500 )edit

imgResult is a class Variable so the result of the function is stored in a variable which is not freed at the end of the function. Moreover, here I have to do it from Python to do an example but the final goal is to use the DLL from Python, C++, LabVIEW and MATLAB. But I start with Python because I already know how to do a GUI in Python.

MathieuG gravatar imageMathieuG ( 2018-08-13 03:48:50 -0500 )edit