VS C++调用python、opencv + 深度学习实例

在项目中,我们经常同时拥有Python和C++的代码,比如用Python跑深度学习,然后后续工程用C++实现,一种较为简便的实现方式为在Python和C++之间相互调用函数,而无需繁琐的代码转换。

下面介绍在Winsdows10Visual Studio2022,用C++调用Python程序的环境配置和测试代码,以及opencv4的环境配置。

一、Anaconda中新建虚拟环境

查看Anaconda虚拟环境位置(Python3.7)

(base) C:\Users\LENOVO>python
>>> import sys
>>> sys.path
//输出结果
['', 'E:\\Anaconda\\anaconda\\python37.zip', 'E:\\Anaconda\\anaconda\\DLLs', 'E:\\Anaconda\\anaconda\\lib', 'E:\\Anaconda\\anaconda', 'E:\\Anaconda\\anaconda\\lib\\site-packages', 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32', 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32\\lib', 'E:\\Anaconda\\anaconda\\lib\\site-packages\\Pythonwin']

我的虚拟环境目录是:

E:\Anaconda\anaconda

安装配置好虚拟环境,对已有python代码进行测试,确定能够在Pycharm等IDE中能够跑通。

二、建立测试代码

C++调用Python其实就是建立了一个Python解释器。
在VS中,首先新建一个C++工程(命名:C_yolo7,设为启动项目),然后在同一个解决方案中新建Python工程(命名:Py_yolo7)。
目录如图所示:
VS C++调用python、opencv + 深度学习实例_第1张图片
C++中新建一个C_yolo7.cpp文件,代码如下:

#include <Python.h>
#include <iostream>
using namespace std;

int main()
{
    cout << "load env " << endl;
	
	//1、初始化python接口
    Py_Initialize(); 
    if (!Py_IsInitialized()) {
        cout << "python init fail" << endl;
        return 0;
    }

    //初始化变量为NULL
    PyObject* pModule = NULL;
    PyObject* pFunc = NULL;
    PyObject* pName = NULL;

    //2、初始化python系统文件路径,保证可以访问到 .py文件
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('../Py_yolo7')"); //../Py_yolo7是C++所调用的Python文件所在的路径,路径一定要对。
    
    //3、调用python文件名。当前的测试python文件名是 Py_yolo.py
    pModule = PyImport_ImportModule("Py_yolo");
    if (pModule == NULL) {
        cout << "module not found" << endl;
        return 1;
    }

    //4、调用函数
    pFunc = PyObject_GetAttrString(pModule, "AdditionFc");
    if (!pFunc || !PyCallable_Check(pFunc)) {
        cout << "not found function add_num" << endl;
        return 2;
    }

    //5、给python传参数
    PyObject* pArgs = PyTuple_New(2);
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2));
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4));

    // 6、使用C++的python接口调用该函数
    PyObject* pReturn = PyEval_CallObject(pFunc, pArgs);

    // 7、接收python计算好的返回值
    int nResult;
    PyArg_Parse(pReturn, "i", &nResult);
    cout << "return result is " << nResult << endl;

    //8、结束python接口初始化
    Py_Finalize();
    return 0;
}

Python中新建两个文件Py_yolo.py和debug.py,代码如下:
Py_yolo.py

from debug import add

def AdditionFc(a, b):
    print("Now is in python module")
    c = add(a, b)
    #c = a+b
    print("{} + {} = {}".format(a, b, c))
    return c

debug.py

import numpy
import cv2

def add(a, b):
	print("hello")
	return a + b + 2

目的:在C_yolo7.cpp中调用Py_yolo.py中的函数,同时Py_yolo.py又会调用debug.py中的函数,在debug.py中引入Python第三方库numpy和cv2,全面进行测试。

三、Visual Studio配置C++调用Python函数所需的环境

按照之前配置的Anaconda虚拟环境及其位置
1.右键C++工程,选择属性页
2.在VC++目录中,配置
包含目录:

E:\Anaconda\anaconda\include

库目录:

E:\Anaconda\anaconda\libs

VS C++调用python、opencv + 深度学习实例_第2张图片
4.链接器->输入,添加附加依赖项:

python37.lib

5.配置环境变量
在系统变量-path中添加:

E:\Anaconda\anaconda
E:\Anaconda\anaconda\Scripts
E:\Anaconda\anaconda\Library

以及编辑系统变量

PYTHONHOME=E:\Anaconda\anaconda

VS C++调用python、opencv + 深度学习实例_第3张图片
VS C++调用python、opencv + 深度学习实例_第4张图片
至此,C++调用Python.h没有问题

若在Py文件中不能成功导入Python第三方库,可以尝试以下两个办法:
方法一
将下面两个文件夹复制到C++编译的exe同目录下:

E:\Anaconda\anaconda\DLLs
E:\Anaconda\anaconda\Lib
//复制到这个文件夹下,xxx是C_yolo7 C++工程所在目录
×××\x64\Release\

方法二
在Anaconda环境中,进入所需的虚拟环境,conda list或者pip list查看已经安装的Python第三方库,把在项目中所需的Python第三方库卸载后重新安装一遍即可(没安装的库安装一下),这个方法解决因环境冲突导致的问题。

(base) C:\Users\LENOVO>conda list
(base) C:\Users\LENOVO>pip3 uninstall xxx
(base) C:\Users\LENOVO>pip3 install xxx //xxx为第三方库名

四、C++调用Python运行结果

load env
Now is in python module
hello
2 + 4 = 8
return result is 8

xxx\Cyolo\C_yolo7\x64\Release\C_yolo7.exe (进程 1064)已退出,代码为 0。
按任意键关闭此窗口...

五、Visual Studio 2022配置opencv4

1、官网下载opencv4版本
2、打开C++工程属性页面(路径依据个人路径而定):
包含目录:

E:\opencv\opencv\build\include

库目录:

E:\opencv\opencv\build\x64\vc15\lib

3、链接器->输入,添加附加依赖项:

opencv_world460.lib

4、配置环境变量:
系统变量 path中添加:

E:\opencv\opencv\build\x64\vc15\bin

建议重启电脑使环境变量生效。
5.测试代码

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("E:\\opencv\\opencv_vs_test\\bus.jpg"); //添加自己的图片路径
	namedWindow("opencv_test");
	imshow("opencv_test", img);
	waitKey(0);
	return(0);

}

运行结果显示图片表示测试成功!

六、Some Tips

1、在c++中使用numpy库C++中使用numpy库

2、Python训练好深度模型(比如yolov7)后,一定要检查Python运行环境配置完全正确,才能在C++中正确调用,因为C++调用Python程序不正确时是不报错的,只会返回NULL,故如果程序能够在Pycharm等IDE中能跑通前提下,出错基本只能在环境配置和文件搜索路径上出问题了。
以下是C++利用opencv4读取图片,将图片数据传入Python中的yolov5进行推理,并将推理结果返回至C++的运行结果:
VS C++调用python、opencv + 深度学习实例_第5张图片
VS C++调用python、opencv + 深度学习实例_第6张图片

3、numpy C++调用Python部分官方文档numpy C++调用Python部分官方文档

4、C中处理Python的Numpy数组的代码范例
C中处理Python的Numpy数组的代码范例

后续更新如何在Linux下Python调用C++和C++调用Python,以及Windows下Python调用C++。

你可能感兴趣的:(VS C++调用python、opencv + 深度学习实例)