以下是c++调用python,c++块代码:
实现:
1、对python的调用
2、传入mat图像矩阵,解析为python对象,再使用python代码进行检测,返回结果
3、对结果进行解析,添加相应处理
#include<D:\software\python\py37\include\Python.h>
#include<opencv.hpp>
#include<dnn.hpp>
#include<arrayobject.h>
#include<imgproc.hpp>
#include<highgui.hpp>
#include<fstream>
#include<sstream>
#include<vector>
#include<filesystem>
#include<io.h>
#include<iostream>
#include<string.h>
using namespace std;
//
void get_need_file(string path,vector<string>&file,string ext);
int main()
{
Py_SetPythonHome((wchar_t*)L"D:\\software\\python\\py37\\"); //设置所使用python环境的路径
Py_Initialize(); //完成Python解释器的初始化
PyRun_SimpleString("import sys"); //导入库,用于添加路径信息
PyRun_SimpleString("import cv2"); // 导入库(python代码里导入的一致)
PyRun_SimpleString("import numpy as np");
PyRun_SimpleString("import os");
PyRun_SimpleString("import torch");
PyRun_SimpleString("import onnxruntime");
PyRun_SimpleString("import torchvision");
PyRun_SimpleString("import time");
PyRun_SimpleString("import os");
PyRun_SimpleString("import random");
//PyRun_SimpleString("sys.path.append(r'D:\\pycharm_project')");//
PyRun_SimpleString("sys.path.append(r'./')");//当前路径添加到Python sys路径
clock start,finish; //时间函数
start=clock();
import_array();
//设置一些Python解释器中的对象
PyObject* pModule = NULL;
PyObject* pFunc = NULL;
PyObject* pParams = NULL;
PyObject* pResult = NULL;
//pModule = PyImport_ImportModule("yolo5");
pModule = PyImport_Import(PyUnicode_FromString("yolo5"));
if (pModule == NULL)
{
cout << "don't find the python file!" << endl;
}
pFunc = PyObject_GetAttrString(pModule, "run");
// 单张图像,或者一个图像文件夹路径
//pParams = Py_BuildValue("(s)", "D:/pycharm_project/yolov5-6.1/data/images/bus.jpg");
//pParams = Py_BuildValue("(ii)", 1, 1);
// 用于测试:处理12张图像为mat,并写入vector
vector<Mat> mats;
string source = "d:\\xxx\\xxx" ; //图片路径
vector<string> my_file;
string need_extension=".PNG";
get_need_file(source,my_file,need_extension);
for (size_t i=0;i<my_file.size(),i++)
{
Mat src=cv::imread(my_file[i],1);
mats.push_back(src);
}
// 把12张mat图像 转为python对象,传给python进行处理
PyObject* listargs=PyTuple_New(12);
for (int j=0;j<12;j++)
{
cv::Mat mat=mats[j];
npy_intp dims[3]={mat.rows,mat.cols,mat.channels()};
PyObject* PyArray=(PyObject*)PyArray_SimpleNewFromData(3,dims,NPY_UBYTE,(unsigned char *)mat.data);
PyTuple_SetItem(listargs,j,PyArray);
}
PyObject* arglist=PyTuple_New(1);
PyTuple_SetItem(arglist,0,listargs);
//只是处理一张图像
/*
PyObject* arglist=PyTuple_New(1);
npy_intp dims[3]={img.rows,img.cols,img.channels()};
PyObject* PyArray=(PyObject*)PyArray_SimpleNewFromData(3,dims,NPY_UBYTE,(unsigned char *)img.data);
PyTuple_SetItem(arglist,0,PyArray);
*/
//调用函数,返回处理结果
pResult = PyObject_CallObject(pFunc, arglist);
// 由于调试,判断python文件在调用运行是否有错
if (PyErr_Occurred) {
PyErr_Print();
PyErr_Clear();
}
if(pResult==NULL){
cout<<"res is null"<<endl;
}
Py_DECREF(arglist);
Py_DECREF(pFunc);
// 创建一些变量
int x,y,count=0;
string *dirpath=nullptr;
vector<Point> &Vpoint;
//map<int, vector<Point>*pMapcoordinate>;
if(PyList_Check(pResult)){
int sizeofarray=PyList_Size(pResult)-1;
PyObject* ne=PyList_GetItem(pResult,sizeofarray); // 图像渲染的地址
for(int i=0;i<sizeofarray;i++){
count+=1;
PyObject* next=PyList_GetItem(pResult,i);
PyArg_ParseTuple(next,"i|i",&x,&y);
Point coordinate(x,y);
Vpoint.push_back(coordinate);
//pMapcoordinate->insert(make_pair(1,Vpoint));
}
PyArg_ParseTuple(ne,"s",&dirpath); //解析:图像渲染地址写到list,和中心点在一起
}
for(vector<Point>::iterator iter=Vpoint.begin();iter!=Vpoint.end();++iter){
cout<<*iter<<endl;
}
finish=clock();
Py_Finalize(); //释放所有Python申请的资源
count<<"all time:"<<finish-start<<endl;
}
// 遍历文件夹所有图像
void get_need_file(string path,vector<string>&file,string ext){
intptr_t file_handle=0;
struct _finddata_t file_info;
string temp;
if((file_handle=_findfirst(temp.assign(path).append("/*"+ext).c_str(),&file_info))!=-1){
do{
file.push_back(temp.assign(path).append("/").append(file_info.name);
}while(_findnext(file_handle,&file_info)==0);
_findclose(file_handle);
}
}
python端代码:
1、使用多线程并行处理图像
inport concurrent
def run(source):
mode=YOLOV5("xx.onnx)
count_all=0 #检测数目
coor=[] #中心坐标点
img_files=[os.path.join(source,file) for file in os.listdir(source)]
# 启动12个线程,如果读取命名是数字的图片,可能导致无序。字母命名的正常
# 使用for循环,指定数据路径,图片每次检测都是不变的,但是速度会慢
with concurrent.futures.ThreadPoolExecutor(max_workers=12) as executor:
furures=[executor.submit(model.inference,imgpath) for imgpath in img_files]
concurrent.futures.wait(futures)
for future in concurrent.futures.as_completed(futures):
outboox=fliter_box(future.result()[0],0.1,0.2)
res,count=draw(future.result()[1],outboox)
count_all+=count
coor.append(res)
executor.shutdown()
return count_all,coor
run("d:/img_path")