图像处理系列文章目录
前言
图像处理算法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调用动态链接库
方法1: xxx.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
方法2: xxx.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后处理耗时几乎可忽略
总结
简单记录一下