版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lhanchao/article/details/78586610
今天需要在C++程序中调用Python的程序,以完成不同功能的整合,以前以为C++中调用Python程序应该比较容易,没想到今天走下来也趟了不少的坑,记录一下。
一、codeblocks的环境配置
因为我的C++程序是在Ubuntu 16.04下用codeblocks建立的工程,所以需要在codeblocks下搭一下调用Python程序时需要的环境。下面来简单介绍一下
我在网上看到了有人在windows下使用codeblocks搭调用python环境的过程(原文见
codeblock中使用C++调用python文件——西北有高楼的博客),但是Linux下却没有资料,我自己搭了一下,方便后来人。
(1)首先自己建立一个工程,右键工程名,选择Build Option,选择Search directories选项卡,在Compiler中选择添加"
/usr/include/python2.7"路径,如图所示;
(2)还是在Search directories选项卡中,选择Linker,添加“/usr/lib/python2.7”路径,如图所示
(3)在Linker Settings选项卡中,在Link Libiaries中添加“/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so”路径,如下图所示:
至此环境搭建完成,后面可以直接写程序调用Python的程序了。
二、C++程序调用Python程序(简单方法)
在网上可以很容易的查到很多C++程序调用Python的方法,但是我的需求特别简单,只要调用我自己Python程序中的一个函数即可,所以我这里用的最简单的方法。
我要调用的Python程序如下:
其实这个程序没什么可看的,我就是训练了一个目标检测和识别的模型,然后用这个函数整合了一下,把最后的结果写到文件里。C++调用它的目的就是为了得到检测的结果,然后使用这个结果进行后续的处理,所以这个程序主要看函数名和函数的参数即可。
#coding=utf-8
#!/usr/bin/env python
'''
Created on 2017年11月20日
@author: hanchao
'''
import cv2
import numpy as np
import os
import os.path
import demo_save_detect
import classify_symbols
#其实这个函数没啥可看的,注意参数和函数名即可。
def get_detect_classify_results(imagename, symbol_label_filename, weights_filename, model_filename, resultname):
image_name = imagename
tmp_image = cv2.imread(image_name)
print tmp_image.shape
image = tmp_image
if tmp_image.ndim == 3:
image = cv2.cvtColor(tmp_image, cv2.COLOR_BGR2GRAY)
detected_boxes = demo_save_detect.detect_symbols(image_name)
images_to_recog, prob_classnum = classify_symbols.prepare_images(image, detected_boxes)
transformer, net, labelnames = classify_symbols.load_modelweights(symbol_label_filename, weights_filename, model_filename)
detect_classify_results = open(resultname, 'w')
i = 0
detect_classify_results.write(str(len(images_to_recog)) + '\n')
for i in range(len(images_to_recog)):
image = images_to_recog[i]
bbox = detected_boxes[i]
image = image / 255.0
classify_result = classify_symbols.inference(image, transformer, net, labelnames)
detect_classify_results.write(str(int(bbox[0])) + ' ' + str(int(bbox[1])) + ' ' + str(int(bbox[2])) + ' ' + str(int(bbox[3])) + ' ' + \
str(classify_result[0][0]) + ' ' + str(classify_result[0][1]) + ' ' + \
str(classify_result[1][0]) + ' ' + str(classify_result[1][1]) + '\n')
detect_classify_results.close()
然后我调用的程序完全是仿照
浅析 C++ 调用 Python 模块——liuwons的博客中的方法,简单的调用了一下上面这个函数,我的调用程序如下:
#include "python2.7/Python.h"//注意一下这里,这是需要这样引入Python
#include <iostream>
using namespace std;
//程序是从上面链接的源码copy过来的,根据我的需求改动了一下。
int main()
{
Py_Initialize(); // 初始化
// 将Python工作路径切换到待调用模块所在目录,一定要保证路径名的正确性
string path = "/home/hanchao/pva-faster-rcnn/tools";
string chdir_cmd = string("sys.path.insert(0,\"") + path + "\")";//注意这里我与前面链接中代码不同,链接中代码在我这里不适用,原因未知
const char* cstr_cmd = chdir_cmd.c_str();
PyRun_SimpleString("import sys");
PyRun_SimpleString(cstr_cmd);
// 加载模块,这里是我前面那个函数所在的模块的名称
PyObject* moduleName = PyString_FromString("detect_classify_utils"); //模块名,不是文件名
PyObject* pModule = PyImport_Import(moduleName);
if (!pModule) // 加载模块失败
{
cout << "[ERROR] Python get module failed." << endl;
return 0;
}
cout << "[INFO] Python get module succeed." << endl;
// 加载函数
PyObject* pv = PyObject_GetAttrString(pModule, "get_detect_classify_results");
if (!pv || !PyCallable_Check(pv)) // 验证是否加载成功
{
cout << "[ERROR] Can't find funftion (test_add)" << endl;
return 0;
}
cout << "[INFO] Get function (test_add) succeed." << endl;
// 设置参数
PyObject* args = PyTuple_New(5); // 5个参数
PyObject* arg1 = PyString_FromString("008831.jpg");
PyObject* arg2 = PyString_FromString("trainSymbolImage_labels.txt");
PyObject* arg3 = PyString_FromString("conv8Net_fc_iter_202000.caffemodel");
PyObject* arg4 = PyString_FromString("deploy.prototxt");
PyObject* arg5 = PyString_FromString("008831.jpg_results");
PyTuple_SetItem(args, 0, arg1);
PyTuple_SetItem(args, 1, arg2);
PyTuple_SetItem(args, 2, arg3);
PyTuple_SetItem(args, 3, arg4);
PyTuple_SetItem(args, 4, arg5);
// 调用函数
PyObject* pRet = PyObject_CallObject(pv, args);
Py_Finalize();
return 0;
}
我这里就图了个方便,完成了我的需求就行,没考虑更深入的东西,更多C++调用Python的资料可以参考 知乎——如何实现 C/C++ 与 Python 的通信?