1.c++调用python的步骤
2.直接上代码进行注释
#include <python2.7/Python.h>
//python与c++的接口在这个头文件里
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <numpy/ndarrayobject.h>
//使用PyArray需要包含此头文件,用于在python和c++之间进行涉及列表和数组之间的数据操作
#include <importance.h>
//这是一个重要第三方头文件用于python cv2和c++ mat之间的转换
void init_numpy(){
import_array();//头文件包含了numpy的头文件,使用其来调用numpy库
}
int main(){
cv::Mat img=cv::imread("/home/CLionProjects/untitled2/2.png");
Py_Initialize();//用于初始化python,可以认为是调用python的解释器和import 一些库
init_numpy();//初始化调用numpy
PyRun_SimpleString("import sys");//该函数意味在python解释器下执行import sys引入
PyRun_SimpleString("import string");//同上
PyRun_SimpleString("sys.path.append('/home/CLionProjects/untitled2/src/python')");//指定即将调用的python文件的绝对地址,如果python文件和c++主程序文件在同一工程目录下,也可以替换为 ./
PyRun_SimpleString("print sys.path");//调用python的解释器输出python解释器的路径和lib的路径等相关信息
if(!Py_IsInitialized())//判断是否初始化,若初始化Py_IsInitialized()为true
{
std::cout<<"not initialize"<<std::endl;
}
PyObject * p_name= PyString_FromString("qwer");
//将c++下的字符串转换为Python*对象,便于python调用,qwer为要使用的python的文件名,不带.py
PyObject * p_module= PyImport_Import(p_name);
//引入该模块即python文件
if(!p_module)
{
std::cout<<"not p_module"<<std::endl;
}
PyObject * p_dict= PyModule_GetDict(p_module);
//将Python文件内的python函数名,类名赋予字典属性,就是通过函数名类名名字找到指定函数或者类
if(!p_dict)
{
std::cout<<"not dict"<<std::endl;
}
PyObject * p_class= PyDict_GetItemString(p_dict,"DQ");
//通过python文件内的类名“DQ”找到对应的类DQ用PyObject*代替
if(!p_class)
{
std::cout<<"not p_func"<<std::endl;
}
PyObject * p_instance= PyInstance_New(p_class,NULL,NULL);
//将刚刚找到的DQ类进行初始化,类似c++对象的实例化
//transform mat numpy to python
//start,,,,这下面可以将c++ mat转换为python cv2,我并未使用,因为在转回来时回不来了,笑哭
/*
auto sz=img.size();
获取图像的尺寸
int wx=sz.width;int hy=sz.height;int cz=img.channels();//获取图像的宽和高及通道
数
int ichannels=img.channels();int irows=img.rows;int icols=img.cols*ichannels;
//因为传入的是三通道rgb图像需要将对遍历方法做准备,icols为三通道的所有的列数,这个和彩色图在内存上的存储方式有关,可以认为共用行数,;灰度图的每一列现在彩色图这边是三列,
if(img.isContinuous())//判断图像是否连续有些时候,因为转换格式的不同,导致在内存上可能有缝隙
{
icols*=irows;
irows=1;
}
uchar *p;//遍历图像的指针
uchar * arrays=new uchar[wx*hy*cz];//存储图像所有像素点的数组
for(int i=0;i<irows;i++)
{
p=img.ptr<uchar>(i);//mat智能指针用于指向图像的第i行的开头
for(int j=0;j<icols;j++)
arrays[++id]=p[j];//遍历图像++id起始为0,
}
npy_intp Dim[3]={hy,wx,cz};//设置数组维数
PyObject * pyarray= PyArray_SimpleNewFromData(3,Dim,NPY_UBYTE,arrays);
将c++数组转换为PyObject对象,3是三个维度,Dim[0]=Dim[1]=Dim[3]=hy*wx意为每一维度多少元素,数组类型和数组
//end
PyObject * arg= PyTuple_New(1);
//声明一个PyTuple元组,在Python中元组作为容器,用来存放参数,返回值;就像一座雀桥(API,c++牛郎在这头,python织女在那头),喜鹊(Tuple)来运送 信息(参数,返回值),不论你的信息是什么,都要喜鹊转达告知对方,对不对
PyTuple_SetItem(arg,0,pyarray);
//刚刚创建的元组是空的,使用该函数对它赋值,在arg元组第0个位置(本身就一个元素)加入数组pyarray
PyObject * d_result=PyObject_CallMethod(p_instance,"run","O",arg);
//调用类内方法,p_instance是PyObject*类型的类的实例化对象,run为想要调用的方法名,“O”为传入参数格式,详情见文档,arg就是要传入参数了,返回值也是pb(PyObject)对象
// python's cv2 transfrom to c++'s mat,这个对于我来说是行不通的,有知道的大佬可以分享一下,嘿嘿
//start
PyObject *redt;int *zero;//定义两个pb对象用于接收元组解析出来的元素值,就是喜鹊卸货了,你要有东西接着
//if(PyTuple_Check(d_result)){
//判断是否为元组,万一送信的不是喜鹊呢
std::cout<<"is a tuple"<<std::endl;
PyArg_UnpackTuple(dwt_result,"ref",2,2,&redt,&zero);
//这个函数用于卸货,第一个2是该元组上最少有几个元素,第二个2是该元组上最多有几个元素,分别用redt,和zero的引用去装,本来返回的是图像,只有一个但是图像的格式是buffer不知道咋处理,又返回多一个值,0
int py_aaray_dims= PyArray_NDIM(redt);//获取返回值的维度信息
npy_intp *py_aaray_shape=PyArray_DIMS(redt);//每个维度的形状
npy_intp array_row=py_aaray_shape[0];//row
npy_intp array_col=py_aaray_shape[1];//col
npy_intp array_high=py_aaray_shape[2];//channels
std::cout<<py_aaray_dims<<","<<*py_aaray_shape<<","<<array_row<<"x"<<array_col<<"dims"<<array_high<<std::endl;
cv::Mat dtimg(array_row,array_col,CV_8UC3, PyArray_DATA(redt));
//构造图像,
delete []arrays;//删除使用的指针
//}
//!!!以上注释的代码没有用到。。。。
*/
importance c;//构造一个对象,用于调用cv2 与mat的转换函数
PyObject * pyarray=c.toNDArray(img);//将mat图像转换成pb对象用于传入python-cv2
PyObject * arg=PyTuple_New(1);//同上面讲
PyTuple_SetItem(arg,0,pyarray);//同上
PyObject * d2_result=PyObject_CallMethod(p_instance,"run","O",arg);//同上
cv::Mat detimg=c.toMat(d2_result).clone();//将pb的n维数组转换成mat,防止数据出错,使用clone()深拷贝
detimg.cv::Mat::convertTo(detimg,CV_8UC3);//转换图像格式
cv::imshow("1", detimg);
cv::waitKey(0);
//end
/*
//PyObject * tuple= PyTuple_New(2);
//PyTuple_SetItem(tuple,0, Py_BuildValue("i",a));
//同上,Py_BuildValue函数用来构造pb对象,这里可以看做对int型变量a,构造成一个pb类型
//PyTuple_SetItem(tuple,1, Py_BuildValue("i",b));
//PyObject * result=PyObject_Call(p_func,tuple,NULL);
//调用一个函数(类外的),函数名为p_func,参数为tuple
//int resul;
//PyArg_Parse(result,"i",&resul);
//单个元素元组解析
//std::cout<<resul<<std::endl;
*/
//下面用于释放指针,不然容易造成内存泄漏
Py_DecRef(d_result);
Py_DecRef(pyarray);
Py_DecRef(arg);
Py_DecRef(p_instance);
Py_DecRef(p_class);
Py_DecRef(p_dict);
Py_DecRef(p_module);
Py_DecRef(p_name);
Py_Finalize();//释放掉python解释器
return 0;
}
3.CmakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(dt
)
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Release)
ENDIF()
MESSAGE("Build type: " ${CMAKE_BUILD_TYPE})
set(OpenCV_DIR "/usr/local/opencv3.4/share/OpenCV")
set(Python_ADDITIONAL_VERSIONS "2.7")
#This is to avoid detecting python 3
find_package(PythonLibs 2.7 EXACT REQUIRED)
if (NOT PythonLibs_FOUND)
message(FATAL_ERROR "PYTHON LIBS not found.")
else()
message("PYTHON LIBS were found!")
message("PYTHON LIBS DIRECTORY: " ${PYTHON_LIBRARY} ${PYTHON_INCLUDE_DIRS})
endif()
find_package(OpenCV 3.4 QUIET)
find_package(PythonLibs REQUIRED)
if (NOT PythonLibs_FOUND)
message(FATAL_ERROR "PYTHON LIBS not found.")
else()
message("PYTHON LIBS were found!")
message("PYTHON LIBS DIRECTORY: " ${PYTHON_LIBRARY})
endif()
include_directories(
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/include
${PYTHON_INCLUDE_DIRS}
/usr/include/python2.7/
/usr/lib/python2.7/dist-packages/numpy/core/include/numpy/
)
add_library(${PROJECT_NAME} SHARED
src/importance.cc
)
target_link_libraries(${PROJECT_NAME}
${OpenCV_LIBS}
/usr/lib/x86_64-linux-gnu/libpython2.7.so
)
add_executable(main test.cpp)
target_link_libraries(main ${PROJECT_NAME})
4.看到一些比较有用的链接也参考了一些
C调用Python(传递数字、字符串、list数组(一维、二维),结构体)
linux C++调用python脚本:C++opencv数据与python opencv数据交互
Python + C/C++ 嵌入式编程(1):多维数组Numpy.Array()在Python和C/C++文件间的传递问题
目录1.for循环2.if判断1.for循环for i in [取值列表] 可以取:数字 字符串 命令结果`` 序列do 要执行什么命令done案列:测试1-255有多少个IP地址在线(能ping通则在线)10.0.0.1-255ping -c2 -w1 10.0.0.2 >/dev/null 2>&1echo $?案例:批量创建10个用户1)前缀为自己输入的字符 输入用户处加判断是否为空2)创建用户个数 判断是否是整...
使用Toolbar,要把原本的 ActionBar 隐藏起来。<style name="AppTheme" parent="AppTheme.Base"/><style name="AppTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="windowActionBar">false</item>
使用Excel导入数据的时候,避免不了校验数据这个过程,在使用EasyExcel进行数据校验的时候,在AnalysisEventListener中抛异常要使用ExcelAnalysisException而不是自己定义的运行时异常,EasyExcel会捕捉所有的非ExcelAnalysisException异常并封装成ExcelAnalysisException抛出,如下。 private void onException(AnalysisContext analysisContext, Except
TOKEN_PAD = '' # Token for padding 填充标记TOKEN_UNK = '&lt;UNK&gt;' # Token for unknown words 未登录词标记TOKEN_CLS = '&lt;CLS&gt;' # Token f...
该系统分为前后台,普通用户与管理员两种角色,前台普通用户登录,后台管理员登录;用户角色包含以下功能:提交订单,查看图书列表,查看图书详情,查看订单,查看购物车,用户登录等功能。管理员角色包含以下功能:一级分类管理,分类管理,发货,图书信息管理,添加图书,订单管理等功能。1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;3.tomcat环境:Tomcat 7.x,8.x,9
转载自本文,以供个人查阅,感谢作者,查看原文请点击OWL属性1.属性概述 RDF/OWL里都是用二元关系来描述东西的,比如描述:比尔盖茨是一个人,在RDF/OWL里就是这样描述的:比尔盖茨 ——是——> 人。其中,比尔盖茨 和 人 之间的那个关系“——是——>”就是RDF/OWL里的属性。 属性:就是一个二元关系。OWL里包括两种属性: 1. 类型属性(...
get方法传参get方法传参,我们只需要把要传递的参数拼接到要发送的路径地址后面。实例前端:export default { data () { return { name: "david", //要传递的值1 age: 20, //要传递的值2 } }, methods: { //在method里面定义一个向后端传递参数的方法,我这里使用的是async await方法向后端传递参数(注:async await是配套使用的),'http://l
今天我们的目标程序是 MyUninstaller 1.34 版。这是一个非常小的程序卸载工具,VC6编写,大小只有61K。我拿到的这个是上次闪电狼兄弟给我的,附带在里面的简体中文语言文件是由六芒星制作的。这个程序有个毛病:就是在列出的可卸载程序上双击查看属性时,弹出的属性窗口的字体非常难看,应该就是系统字体(SYSTEM_FONT):我们今天的目标就是利用 OllyDBG 的汇编功能把上面显示的字体改成我们常见的9号(小五)宋体。首先我们用 OllyDBG 载入程序,按 CTR+N 组合键查找一下有哪些
1 rebalance带来的问题1.1 主题分区和消费者群组KafkaConsumer从Kafka订阅Topic,并从订阅的Topic拉取消息。Kafka的消费者属于消费者群组,一个群组的消费者订阅的是同一个主题,每个消费者接收主题一部分分区的消息。每个分区只能被消费者群组的一个消费者接收消息,如果一个消费者群组的消费者数多于一个主题的分区数,则多余的消费者会空闲。如果主题T1有4个分区,那么消费者群组1有1个、2个、4个和5个消费者的话,与分区的连接情况分别如下:.
全局讲解ArcGIS Engine开发课程,初级学习
现如今,随着科技的发展,我们已经进入了人工智能和大数据的时代。人工智能和大数据采集涉及到一个东西,那就是数据。但是,面对如此庞大的数据库,人类一点都收集不到,那么爬虫就会被利用。爬虫并不是万能的,在抓取数据的过程中很可能是反爬虫的,于是IP代理诞生了。代理IP本质是隐藏自己的IP地址,用新的IP代替访问操作。我们在获取代理IP的时候,先用电脑连接到代理IP(新IP),然后通过代理服务器上线,网页的内容通过代理服务器送回你自己的电脑。这样可以保证数据信息的安全性。网上有很多专业的代理IP服