Python调用C++ DLL实现OpenCV Mat与Numpy Array互转

Mia
Mia
发布时间:2026-10-15 | 2人浏览过
原创

本文详细解析在Python调用C++生成的DLL时,如何处理OpenCV图像数据类型的转换。重点讲解Python中Numpy Array与C++中cv::Mat通过unsigned char指针进行交互的方法,包括数据传递、内存拷贝及返回值处理的具体代码实现。

关于Python调用C++动态库DLL时的参数传递问题

以下是生成C++动态链接库(DLL)的源代码示例:

#include <iostream>
extern "C" __declspec(dllexport) int get_str_length(char *str);
int get_str_length(char *in_str)
{
	std::string str(in_str);
	return str.length();
}

编译生成的VS_create_dll.dll文件需放置在与Python脚本相同的目录下。随后编写Python调用代码:

import ctypes as C
dll = C.cdll.LoadLibrary('VS_create_dll.dll')
#4.1 传入字符串调用demo 方法一
p_str = C.c_char_p(b'hello')#或p_str =  b'hello'
str_length1 = dll.get_str_length(p_str)
print("传入字符串调用demo 方法一:")
print (str_length1)
#4.1 传入字符串调用demo 方法二
get_str_length = dll.get_str_length
get_str_length.argtypes = [C.c_char_p]
get_str_length.restype = C.c_int
str_length2 = get_str_length(p_str)
print("传入字符串调用demo 方法二:")
print (str_length2)

OpenCV Mat数据类型处理

在Python环境中,OpenCV读取的图像数据通常以Numpy Array形式存储;而在C++中,OpenCV使用cv::Mat类。两者之间的数据交换需借助unsigned char指针作为中间桥梁。

具体数据类型对应关系如下:

python: 	C.POINTER(C.c_ubyte)
C++:		unsigned char *

在Python中,将Numpy Array转换为C.POINTER(C.c_ubyte)(对应C++中的unsigned char *)的方法如下:

import ctypes as C
import cv2
img = cv2.imread('ROI0.png')
#将img转换成可被传入dll的数据类型
img.ctypes.data_as(C.POINTER(C.c_ubyte))

在C++端,将接收到的unsigned char *指针转换为cv::Mat对象的方法为:

假设传入的源数据指针变量名为src_data。

Mat src = Mat(rows,cols,CV_8UC3,src_data);

C++中的OpenCV提供了通过unsigned char *构建Mat对象的构造函数,该构造函数还需指定图像的行数、列数及通道数等元数据。因此,Python调用DLL时,除了传递src_data指针外,还必须同时传入rows、cols等维度信息。

在C++端,将cv::Mat转换回unsigned char *指针的方法为:

src.data

OpenCV提供了Mat类的data成员变量,可直接获取指向图像数据缓冲区的unsigned char *指针。

在C++中,使用memcpy函数将Mat.data指向的数据复制到输出缓冲区ret_data中。

memcp(ret_data,src.data,rows*cols*3);

在Python端,将C.POINTER(C.c_ubyte)(对应C++中的unsigned char *)转换回Numpy Array的方法:

#声明并初始化变量
import numpy as np
import cv2
ret_img = np.zeros(dtype=np.uint8, shape=(rows, cols, 3))
#call dll,ret_img.ctypes.data_as(C.POINTER(C.c_ubyte))作为参数传入
cv2.imshow("result",ret_img )

由于在Python中,ret_img在调用DLL前已初始化为Numpy Array类型,且在调用时仅将其作为形参转换为C.POINTER(C.c_ubyte)用于接收数据,因此调用结束后,ret_img无需额外转换即可直接使用。

以下是完整的C++ DLL生成代码示例:

#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
extern "C" __declspec(dllexport) void draw_circle(int rows, int cols, unsigned char *src_data, unsigned char *ret_data);
void draw_circle(int rows, int cols, unsigned char *src_data , unsigned char *ret_data)
{
	//将unsigned char转换成Mat
	Mat src = Mat(rows, cols, CV_8UC3, src_data);
	//在图像上画一个蓝色的圆
	circle(src, Point(60, 60), 10, Scalar(255, 0, 0));
	//将Mat转换成unsigned char
	memcpy(ret_data, src.data, rows*cols * 3);
}

对应的Python调用代码如下:

import ctypes as C
import cv2
import numpy as np
dll = C.cdll.LoadLibrary("draw_circle.dll")
img = cv2.imread('ROI0.png')
(rows, cols) = (img.shape[0], img.shape[1])
ret_img = np.zeros(dtype=np.uint8, shape=(rows, cols, 3))
dll.draw_circle(rows, cols, img.ctypes.data_as(C.POINTER(C.c_ubyte)), ret_img.ctypes.data_as(C.POINTER(C.c_ubyte)))
cv2.imshow("src with circle",ret_img)
cv2.waitKey(0)

参考来源

https://blog.csdn.net/wolfcsharp/article/details/103754514

至此,关于Python调用C++动态库(DLL)时的参数传递及OpenCV数据类型转换介绍完毕。如需了解更多相关技术细节,可搜索本站往期文章或继续浏览后续内容,感谢支持。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表