因毕设需要,需从 python 将图像数据传给 C++,接收 C++ 处理好后的图像。
新建 C++ 文件接收从 Python传来的数据
#include <opencv2/opencv.hpp>cv::BackgroundSubtractorMOG2 mog(100, 16, false);extern "C" void getfg(int rows, int cols, unsigned char* imgData,unsigned char *fgD) {cv::Mat img(rows, cols, CV_8UC3, (void *) imgData);cv::Mat fg(rows, cols, CV_8UC1, fgD);mog(img, fg);}extern "C" void getbg(int rows, int cols, unsigned char *bgD) {cv::Mat bg = cv::Mat(rows, cols, CV_8UC3, bgD);mog.getBackgroundImage(bg);}
所有与 python 交互的 API 必须在 extern "C"中,如果交互 API 过多,上述代码也可以写成如下形式
#include <opencv2/opencv.hpp>cv::BackgroundSubtractorMOG2 mog(100, 16, false);extern "C"{void getfg(int rows, int cols, unsigned char* imgData,unsigned char *fgD) {cv::Mat img(rows, cols, CV_8UC3, (void *) imgData);cv::Mat fg(rows, cols, CV_8UC1, fgD);mog(img, fg);}void getbg(int rows, int cols, unsigned char *bgD) {cv::Mat bg = cv::Mat(rows, cols, CV_8UC3, bgD);mog.getBackgroundImage(bg);}}
图像数据通过 unsigned char *data 传输进来,通过Mat image(h,w,CV_8UC3,data)转换成C++ OpenCV可识别数据,如果是灰度图,则是CV_8UC1,数据通过指针链接,在C中是直接修改存在内存中的数据,无需传回。
之后将 C 编译成动态链接库,CmakeLists设置如下
add_library(prj SHAREDmain.cppmain.h libmain.cpp)target_link_libraries(prj ${OpenCV_LIBS})
与C++交互的文件设置如下
import ctypes# 链接动态库libmog = ctypes.cdll.LoadLibrary('path/to/libmain.so')def getfg(img):(rows, cols) = (img.shape[0], img.shape[1])res = np.zeros(dtype=np.uint8, shape=(rows, cols))libmain.getfg(img.shape[0], img.shape[1],img.ctypes.data_as(ctypes.c_char_p),res.ctypes.data_as(ctypes.c_char_p)return resdef getbg(img):(rows, cols) = (img.shape[0], img.shape[1])res = np.zeros(dtype=np.uint8, shape=(rows, cols, 3))libmain.getbg(rows, cols, res.ctypes.data_as(ctypes.c_char_p))return res
对于需要指针传输的数据,需要用ctypes.data_as(ctypes.c_char_p)将其转换成C++可读取的数据形式
参考文章
stackoverflow
