2

Using Python 3 and OpenCV 3.

I have written some DLL's in C++ that export a few C-type functions and a uchar3 c-type struct. I have been using these with OpenCV in a C++ project, but I would like to be able to access them from Python as well. I am pretty new to Python, but I see that ctypes provides a fairly straightforward way to use DLL's.

What I can't sort out is how to get a pointer to the OpenCV Mat from within Python. Using C++, I do the following:

    myMatDataPointer = myMat.ptr<uchar>(0)

Ideally, I would like to find an easy way to use the uchar3 struct, but I see that a char* is supported out-of-the-box by ctypes, so I can make do with that if I can figure out how to get one pointing to the Mat's data.

7
  • You'd have to create a pure C interface for the library. For C++, try frameworks that need a compiler such as Cython, SWIG, or Boost.Python. Commented May 6, 2016 at 19:43
  • Yes, the dll's export pure C functions (as far as I know, it's not possible to export non-pure-C functions from a dll). The problem is that these functions need a pointer to the OpenCV mat's data. I know how to access this in C++, but not in Python. Commented May 7, 2016 at 23:09
  • There are C++ DLLs (e.g. Microsoft's ulib.dll, a utility library used by console programs), but since there's no cross-platform, stable ABI, it's not a good idea in general, and such DLLs can't be easily used with ctypes. On Windows it's common for C++ devs to create COM DLLs, for which you can use comtypes or pythoncom. Commented May 7, 2016 at 23:42
  • As to getting a pointer, you can write a C stub function that returns the pointer. Generally this calls a C++ constructor to get a this instance for a Python proxy class. The proxy calls C wrappers for the C++ methods, manually supplying the this reference as the first argument. Commented May 7, 2016 at 23:45
  • Is it implicit in your suggested solution that OpenCV does not provide any way of directly accessing a Mat's data via Python as it does in C++? I was really hoping there would be a similarly-simple way to do custom image processing. I didn't quite grasp your suggestion, but it sounds like it would probably just be easier for me to stick with 100% C++. Commented May 8, 2016 at 1:15

1 Answer 1

3

I just realized that this never was answered. I can now provide one that I've been using. It supports bi-directional communication using a pure C interface.

import cv2
import ctypes
import numpy as np
import numpy.ctypeslib as npct

# Tell numpy what kind of pointer we want to use, load the dll
ucharPtr = npct.ndpointer(dtype=np.uint8, ndim=1, flags='CONTIGUOUS')
dll = ctypes.WinDLL('file.dll')

# the 'process_frame' function exported by the dll reads from
# the first pointer and writes to the second
process = dll['process_frame']
process.restype = None
process.argtypes = [ucharPtr, ucharPtr]

# Make two empty images for demonstration purposes
# OpenCV Python uses numpy arrays images, not Mat's
# This makes it super easy to work with images in python
in_image = np.zeros(shape,np.uint8,order='C').ravel()
out_image = np.zeros(self.shape,np.uint8,order='C').ravel()
process(in_image, out_image)

I could have used something more interesting for in_image of course, but we've successfully sent an image from OpenCV python to the dll, and can use whatever our dll gave back.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this, What is the ++ side? how to load the pointer into an opencv Mat?
I actually wasn't using opencv in the C++ code, rather I was using low-level CUDA code to do fast processing on the GPU. That said, IIRC with OpenCV C++ if you have a Mat with correct metadata, you can just change its pointer to wherever your data is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.