详细记录python调用动态链接库.dll和.so的使用方法

图像处理系列文章目录


前言

图像处理算法C++写好编译成动态链接库**.dll 或.so**
使用python调用动态链接库进行逻辑处理,Opencv Mat 输入给动态链接库到输出Mat给python处理的时间效率比较

一、window系统 DLL编译

打开Visual Studio新建 DLL项目 或者 空项目,如果是空项目只需一下设置 .dll 即可
在这里插入图片描述

二、编写代码

xxx.h

#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT void ImageEnhance(int rows, int cols, uchar *src_data, uchar *dst_data);

xxx.cpp

DLLEXPORT void ImageEnhance(int rows, int cols, uchar *src_data, uchar *dst_data)
{
    
    
	cv::Mat src = cv::Mat(rows, cols, CV_8UC3, src_data);
	Mat test2dst = test2(src);  //图像处理函数
	Mat dst = test7(test2dst);
	//uchar* dst_data = (uchar*)malloc(sizeof(uchar) * rows * cols * 3);
	memcpy(dst_data, dst.data, rows * cols * 3);
	//return dst_data;
}

执行编译即可生成xxx.dll文件

三、Linux系统 so编译

编译时选择生成动态链接库即可,如果不知道怎么编译so文件, 自己百度学习下

四、python调用动态链接库

方法1xxx.py

import ctypes
import time
def ImportDLL(img, IE_DLL):
	# if Windows
    IE_DLL = ctypes.CDLL(r"xxx.dll", winmode=0)
    # elif Linux
    ll = ctypes.cdll.LoadLibrary
    IE_DLL = ll("xxx.so")
    
    rows, cols, channel = img.shape[0], img.shape[1], img.shape[1]
    if channel < 3:   # 算法只处理3通道图像
        return -1
    # 获取numpy对象的数据指针
    frame_data = np.asarray(img, dtype=np.uint8)
    input_data = frame_data.ctypes.data_as(ctypes.c_char_p)

    # 设置输出数据类型为uint8的指针
    IE_DLL.ImageEnhance.restype = ctypes.POINTER(ctypes.c_uint8)
    # 调用dll内部的函数
    pointer = IE_DLL.ImageEnhance(ctypes.c_int(rows), ctypes.c_int(cols), input_data)

    # 从指针指向的地址中读取数据,并转为numpy array
    # 这种用np.fromiter处理dll输出的buffer的方法很慢
    t1 = time.time()
    np_result = np.array(np.fromiter(pointer, dtype=np.uint8, count=rows * cols * 3))
    dst = np_result.reshape((rows, cols, 3))
    print("=== dll_buffer to img: ", time.time() - t1)
    cv2.imshow("dst", dst)
    cv2.waitKey(0)
    return pointer, dst

方法2xxx.py ,相较于方法1,buffer后处理时间非常快

import ctypes
import time
def ImportDLL(img, IE_DLL):
	# if Windows
    IE_DLL = ctypes.CDLL(r"xxx.dll", winmode=0)
    # elif Linux
    ll = ctypes.cdll.LoadLibrary
    IE_DLL = ll("xxx.so")
    
    rows, cols, channel = img.shape[0], img.shape[1], img.shape[1]
    if channel < 3:   # 算法只处理3通道图像
        return -1
    # 获取numpy对象的数据指针
    frame_data = np.asarray(img, dtype=np.uint8)
    input_data = frame_data.ctypes.data_as(ctypes.c_char_p)

    # 设置输出数据类型为uint8的指针
    IE_DLL.ImageEnhance.restype = ctypes.POINTER(ctypes.c_uint8)
    # 调用dll内部的函数
    pointer = IE_DLL.ImageEnhance(ctypes.c_int(rows), ctypes.c_int(cols), input_data)

    # 从指针指向的地址中读取数据,并转为numpy array
    t1 = time.time()
    buffer_frome_memory = ctypes.pythonapi.PyMemoryView_FromMemory
    buffer_frome_memory.restype = ctypes.py_object
    buffer = buffer_frome_memory(pointer, rows * cols*3)
    dst = np.frombuffer(buffer, dtype=np.uint8)
    dst = np.reshape(dst, (rows, cols, 3))
    print("=== dll_buffer to img: ", time.time() - t1)
    cv2.imshow("dst", dst)
    cv2.waitKey(0)
    return pointer, dst

五、后处理动态链接库buffer转图像的时间比较

可以看到相较于方法1,方法2后处理耗时几乎可忽略
在这里插入图片描述

总结

简单记录一下

猜你喜欢

转载自blog.csdn.net/zengwubbb/article/details/127305511