C/C++调用Python [opencv与numpy]
目前的情况下,如果你有一个深度学习模型,很想在项目中使用,但模型是用python写的,项目使用的是C++,怎么办?直观的做法是从C++调用python解释器,本文遇到的情景是C++环境下有张图片,需要将其中一个区域(ROI)进行放大(超分辨率重建),放大算法是python环境下的函数(pytorch模型),之后在C++环境下进行后续处理,假设希望从C/C++端调用的python函数如下(暂不介绍超分辨率,用opencv的resize替代):
import cv2 as cv
def super_resolution(img, scale=4):
height, width = img.shape[:2]
dsize = (width*scale, height*scale)
big_img = cv.resize(img, dsize)
return big_img
先介绍环境配置,再讲从C/C++调用Python的关键操作。
1. 环境设置
以windows环境为例,开发时需要做好相关配置,我的环境:Windows10,VS2017 Community,Python3.6.4_x64,OpenCV3.4.1_x64。
OpenCV环境
- Visual Studio配置包含目录(编译错),
D:\Program Files\opencv3\build\include
- Visual Studio配置库目录(链接错),
D:\Program Files\opencv3\build\x64\vc15\lib
- Visual Studio配置链接器输入(链接错):
opencv_world341.lib
- 追加
Path
环境变量(运行错):Path=Path;D:\Program Files\opencv3\build\x64\vc15\bin
,改完环境变量一定要重启Visual Studio才能生效。
下面的例子读取一张图片并显示。
//opencv_demo.cpp
#include<opencv/cv.hpp>
using namespace cv;
int main(int argc, char *argv[]){
Mat img = imread("lena.jpg");
imshow("lena", img);
waitKey(0);
destroyAllWindows();
return 0;
}
Python环境
- Visual Studio配置包含目录(编译错):
D:\Program Files\Python36\include
- Visual Studio配置库目录(链接错):
D:\Program Files\Python36\libs
- 新增环境变量(运行错):
PYTHONHOME=D:\Program Files\Python36
,改完环境变量一定要重启Visual Studio才能生效。
下面的例子从C调用Python解释器,并执行Python代码,打印时间和日期。
//python_demo.cpp
// https://docs.python.org/3.6/extending/embedding.html#very-high-level-embedding
#include <Python.h>
int main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
getchar();
return 0;
}
Numpy环境
- Visual Studio头文件目录(编译错):
D:\Program Files\Python36\Lib\site-packages\numpy\core\include
- 关键代码(运行错):在
Py_Initialize();
之后必须调用import_array();
以加载所有numpy函数(C API),与加载dll类似。
下面的例子展示用numpy接口实现矩阵计算矩阵乘法,并验证结果。
// numpy_demo.cpp
#include <Python.h>
#include <iostream>
#include <numpy/arrayobject.h>
using namespace std;
int main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
import_array(); /* load numpy api */
double array_1[2][3] = {
{
2,5,6 },{
5,6,5 } };
npy_intp dims_1[] = {
2, 3 };
PyObject *mat_1 = PyArray_SimpleNewFromData(2, dims_1, NPY_DOUBLE, array_1);
double array_2[3][4] = {
{
1,