因毕设需要,需从 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 SHARED
main.cpp
main.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 res
def 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