Python与C++动态库之间传递图像数据

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

 

你可能感兴趣的:(opencv,Python)