1.首先搭建编译产生动态库的工程,利用clion,配置好cmakelist.txt,主要是包含OpenCV库及Python.h文件路径,如下:
cmake_minimum_required(VERSION 3.10)
project(cpplib)
PROJECT(${PROJECT_NAME})
set(CMAKE_CXX_STANDARD 11)
add_library(cpplib SHARED library.cpp library.h)
FIND_PACKAGE(OpenCV REQUIRED)
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
target_include_directories(
cpplib PUBLIC
"/usr/include/python3.6"
)
target_link_libraries(cpplib ${OpenCV_LIBS})
2.在library.cpp文件中添加实现方法,下面主要展示封装的接口及内部如何从传入的图像数据解析为OpenCV Mat对象。
// change uchar* to mat
Mat cpplib::readfrombuffer(uchar* frame_data,int height, int width,int channels){
if(channels == 3){
Mat img(height, width, CV_8UC3);
uchar* ptr =img.ptr(0);
int count = 0;
for (int row = 0; row < height; row++){
ptr = img.ptr(row);
for(int col = 0; col < width; col++){
for(int c = 0; c < channels; c++){
ptr[col*channels+c] = frame_data[count];
count++;
}
}
}
return img;
}
}
char* cpplib::mattostring(uchar* frame_data, int rows, int cols, int channels){
Mat mat = readfrombuffer(frame_data,rows,cols,channels);
imwrite("./incoming_image.jpg", mat);
if (!mat.empty()) {
vector data_encode;
vector compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); // png 选择jpeg CV_IMWRITE_JPEG_QUALITY
compression_params.push_back(1); //在这个填入你要的图片质量 0-9
imencode(".png", mat, data_encode);
std::string str_encode(data_encode.begin(), data_encode.end());
char* char_r = new char[str_encode.size() + 10];
memcpy(char_r, str_encode.data(), sizeof(char) * (str_encode.size()));
return char_r;
}
}
//接口部分
extern "C"{
char* mattostring(uchar* matrix, int rows, int cols, int channels)
{
cpplib t;
return t.mattostring(matrix, rows, cols, channels);
}
3.主要展示Python的图像数据转换、数据传入及后面处理完的图像数据转换:
import ctypes
import cv2
import numpy as np
so = ctypes.cdll.LoadLibrary
lib = so("/home/jingzhenyu/clion/cpplib/build/libcpplib.so") # absolute path
src = cv2.imread("466.jpg")
src = np.asarray(src, dtype=np.uint8)
src1 = src.ctypes.data_as(ctypes.c_char_p)
startPt = np.array([128, 233])
endPt = np.array([127, 244])
imgattr = np.array([src.shape[0], src.shape[1], src.shape[2]])
predsPt = np.array([49, 110])
radius = 57.6
curve = 0.7
int_arr3 = ctypes.c_int * 3
imgattr_para = int_arr3()
imgattr_para[0] = imgattr[0]
imgattr_para[1] = imgattr[1]
imgattr_para[2] = imgattr[2]
int_arr2 = ctypes.c_int * 2
startPt_para = int_arr2()
startPt_para[0] = startPt[0]
startPt_para[1] = startPt[1]
endPt_para = int_arr2()
endPt_para[0] = endPt[0]
endPt_para[1] = endPt[1]
predsPt_para = int_arr2()
predsPt_para[0] = predsPt[0]
predsPt_para[1] = predsPt[1]
radius_para = ctypes.c_float(radius)
curve_para = ctypes.c_float(curve)
lib.LocalTransformInterface.restype = ctypes.c_void_p
res = lib.LocalTransformInterface(src1, imgattr_para, startPt_para, endPt_para, predsPt_para, radius_para, curve_para)
print("LocalTransformInterface done")
b = ctypes.string_at(res,imgattr_para[1]*imgattr_para[0]*imgattr_para[2]) # string_at(c_str_p) # 获取内容
print("string_at done")
nparr = np.frombuffer(b, np.uint8)
print("frombuffer done")
img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
print("imdecode done")
imwrite("res_img.jpg", img_decode)
目前还遇到的一点问题是,最后string_at的时候会崩溃,正在查找原因,后续更新这一块。
已定位到原因,需要添加如下代码:
lib.LocalTransformInterface.restype = ctypes.c_void_p