ubuntu C++调用python

news2024/9/24 9:28:32

普通

目录结构
在这里插入图片描述
main.py
等会用c++调用func()

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import os


def func():
    print('hello world')


if __name__ == '__main__':
    func()

main.cpp
其中Py_SetPythonHome的路径是anaconda中环境的路径,最开始的L一定要加(因为代表wchar_t)
sys.path.append是用来找你的python文件路径的,其中 " . " "." "."表示可执行文件的路径

#include <Python.h>
#include <iostream>

int main() {
	Py_SetPythonHome(L"/home/icml/miniconda3/envs/DL");
	Py_Initialize();
	if (0 == Py_IsInitialized()) {
		std::cout << "python init fail" << std::endl;
		return -1;
	}

	PyRun_SimpleString("import sys");
	PyRun_SimpleString("sys.path.append('../python_script')");

	//相当于import
	PyObject* pModule = PyImport_ImportModule("main");
	if (NULL == pModule) {
		std::cout << "module not found" << std::endl;
		return -1;
	}

	PyObject* pFunc = PyObject_GetAttrString(pModule, "func");
	if (NULL == pFunc || 0 == PyCallable_Check(pFunc)) {
		std::cout << "not found function func" << std::endl;
		return -1;
	}


	PyObject_CallObject(pFunc, NULL);

	Py_Finalize();
	return 0;
}

CMakeLists.txt
稍微对照着修改一下就行

cmake_minimum_required(VERSION 3.0.0)
project(C_PLUS_PLUS VERSION 0.1.0)

# IF(NOT CMAKE_BUILD_TYPE)
#   SET(CMAKE_BUILD_TYPE Release)
# ENDIF()

set(PYTHON_INCLUDE_DIRS "/home/icml/miniconda3/envs/DL/include/python3.8")
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
link_directories("/home/icml/miniconda3/envs/DL/lib/python3.8/config-3.8-x86_64-linux-gnu")
set(PYTHON_LIBRARIES "/home/icml/miniconda3/envs/DL/lib/libpython3.8.so")
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})

我这里cmake最后产生到build目录里
在这里插入图片描述

opencv+numpy+pytorch

main.cpp

load_model
加载模型

get_predict_xy
用C++的opencv读图片,转numpy传入python
python再用pytorch预测,返回一个numpy

simple_test
用C++的opencv读图片,转numpy传入python
python直接传回来给C++,转opencv

顺带提一下,import_array()一定要写

#include <Python.h>
#include <iostream>
#include <string>
#include <numpy/arrayobject.h>
#include <opencv2/opencv.hpp>

void load_model(PyObject* pModule, const std::string& model_path){
    PyObject* init_model = PyObject_GetAttrString(pModule, "init_model");
	if (NULL == init_model || 0 == PyCallable_Check(init_model)) {
		std::cout << "not found function init_model" << std::endl;
		exit(-1);
	}
    PyObject *pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", model_path.c_str()));

	PyObject* result = PyObject_CallObject(init_model, pArgs);
	if(NULL == result){
		std::cout << "init_model failed" << std::endl;
		exit(-1);
	}
    int return_value = -1;
    PyArg_Parse(result, "i", &return_value);
    std::cout<<"returned "<<return_value<<std::endl;
}

void get_predict_xy(PyObject* pModule, const std::string& img_path){
	cv::Mat img = cv::imread(img_path, 0);
    PyObject* predict = PyObject_GetAttrString(pModule, "get_predict_xy");
	if (NULL == predict || 0 == PyCallable_Check(predict)) {
		std::cout << "not found function get_predict_xy" << std::endl;
		exit(-1);
	}
	npy_intp dims[] = {img.rows, img.cols};
	PyObject* pValue = PyArray_SimpleNewFromData(2, dims, NPY_UINT8, img.data);
    PyObject *pArgs = PyTuple_New(1);
    // PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", img_path.c_str()));
	PyTuple_SetItem(pArgs, 0, pValue);

	PyObject* result = PyEval_CallObject(predict, pArgs);
	if(NULL == result){
		std::cout << "get_predict_xy failed" << std::endl;
		exit(-1);
	}
	if(!PyArray_Check(result)){//None
		std::cout << "didn't return numpy" << std::endl;
		exit(-1);
	}
	PyArrayObject* ret_array;
	PyArray_OutputConverter(result, &ret_array);
	if(2 != PyArray_NDIM(ret_array)){
		exit(-1);
	}
	npy_intp* shape = PyArray_SHAPE(ret_array);
	int n = shape[0];
	int m = shape[1];
	cv::Mat return_key_points(n,m,CV_32F,PyArray_DATA(ret_array));
	for(int i = 0; i < n; ++i){
		for(int j = 0; j < m; ++j){
			int* cur = reinterpret_cast<int*>(PyArray_GETPTR2(ret_array, i, j));
			std::cout<<*cur<<' ';
			
		}
		std::cout<<std::endl;
	}

	//PyArray_GETPTR2
}


void simple_test(PyObject* pModule, const std::string& img_path){
	cv::Mat img = cv::imread(img_path, 0);
	 PyObject* predict = PyObject_GetAttrString(pModule, "simple_test");
	if (NULL == predict || 0 == PyCallable_Check(predict)) {
		std::cout << "not found function simple_test" << std::endl;
		exit(-1);
	}
	npy_intp dims[] = {img.rows, img.cols};
	PyObject* pValue = PyArray_SimpleNewFromData(2, dims, NPY_UINT8, img.data);
    PyObject *pArgs = PyTuple_New(1);
    // PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", img_path.c_str()));
	PyTuple_SetItem(pArgs, 0, pValue);

	PyObject* result = PyEval_CallObject(predict, pArgs);
	if(NULL == result){
		std::cout << "simple_test failed" << std::endl;
		exit(-1);
	}
	if(!PyArray_Check(result)){//None
		std::cout << "didn't return numpy" << std::endl;
		exit(-1);
	}
	PyArrayObject* ret_array;
	PyArray_OutputConverter(result, &ret_array);
	if(2 != PyArray_NDIM(ret_array)){
		exit(-1);
	}
	npy_intp* shape = PyArray_SHAPE(ret_array);
	int n = shape[0];
	int m = shape[1];
	cv::Mat return_img(n,m,CV_8UC1,PyArray_DATA(ret_array));
	// cv::imshow("test", return_img);
	// cv::waitKey(0);
	// cv::destroyAllWindows();
	for(int i = 0; i < n; ++i){
		uchar* data1 = img.ptr<uchar>(i);
		uchar* data2 = return_img.ptr<uchar>(i);
		for(int j = 0; j < m; ++j){
			if(data1[j] != data2[j]){
				std::cout<<"not equal"<<std::endl;
				return;
			}
		}
	}
	std::cout<<"equal"<<std::endl;
}

int main() {
	Py_SetPythonHome(L"/home/icml/miniconda3/envs/DL");
	Py_Initialize();
	if (0 == Py_IsInitialized()) {
		std::cout << "python init fail" << std::endl;
		return -1;
	}
	import_array(); //这句一定要写
	PyRun_SimpleString("import sys");
	PyRun_SimpleString("sys.path.append('../python_script')");

	//相当于import
	PyObject* pModule = PyImport_ImportModule("predict");
	if (NULL == pModule) {
		std::cout << "module not found" << std::endl;
		return -1;
	}
	simple_test(pModule, "/mnt/data/datasets/landmark/ISBI2015_ceph/raw/001.bmp");
	load_model(pModule, "../python_script/best.pth");
	get_predict_xy(pModule, "/mnt/data/datasets/landmark/ISBI2015_ceph/raw/001.bmp");
	get_predict_xy(pModule, "/mnt/data/datasets/landmark/ISBI2015_ceph/raw/001.bmp");
	Py_Finalize();
	return 0;
}

predict.py
UNet我没放出来

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import os
import numpy as np

from model.u2net import UNet
import torch
from cv2 import cv2
import imgaug.augmenters as iaa

model = UNet(in_channels=1, out_channels=19)
device = torch.device('cuda:0')
augmentation = iaa.Sequential([
    iaa.Resize({"width": 416, "height": 512})
])


def init_model(path):
    global model, device
    if not os.path.exists(path):
        print(f'not found {os.path.abspath(path)}')
        return -1
    model_state_dict = torch.load(path)
    model.load_state_dict(model_state_dict)
    model = model.to(device)
    return 0


def get_img_aug(img):
    global augmentation
    print('----get_img_aug------')
    print(img.shape)
    print('------------------')
    # img = cv2.imread(path, 0)  # 2490*1935
    img_aug = augmentation(image=img)
    img_aug = (img_aug - img_aug.min()) / (img_aug.max() - img_aug.min())
    img_aug = torch.FloatTensor(img_aug).unsqueeze(0).unsqueeze(0)  # torch.Size([1, 1, 512, 416])
    return img_aug


def get_heatmap_coordination_batch_numpy(heatmap):
    """
    get heatmap coordination by batch

    :param heatmap: (B,C,H,W) or (B,C,H,W,D) (C is the num of landmark)
    :return: coordination (B,C,2) or (B,C,3)
    """
    origin_shape = heatmap.shape
    heatmap = heatmap.reshape(*origin_shape[:2], -1)
    temp = np.argmax(heatmap, axis=-1)[..., np.newaxis]

    # unravel_index
    out = []
    for dim in reversed(origin_shape[2:]):
        out.append(temp % dim)
        temp = np.floor_divide(temp, dim)
    out = np.concatenate(out[::-1], axis=-1)
    return out


def get_predict_xy(img):
    global model
    # if not os.path.exists(path):
    #     return None
    img = get_img_aug(img).to(device)# 1 * 1 * 512 * 416
    output = model(img)['output'].to('cpu').detach().numpy() # 1 * 1 * 19 * 2
    predict_xy = get_heatmap_coordination_batch_numpy(output).squeeze(0)  # 19 * 2
    print(predict_xy)
    return predict_xy

def simple_test(img):
    return img

if __name__ == '__main__':
    path = '/mnt/data/datasets/landmark/ISBI2015_ceph/raw/001.bmp'
    init_model('best.pth')
    print('finish_init')
    print(get_predict_xy(path).shape)
    print(get_predict_xy(path).dtype)

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(C_PLUS_PLUS VERSION 0.1.0)

IF(NOT CMAKE_BUILD_TYPE)
  SET(CMAKE_BUILD_TYPE Release)
ENDIF()

set(PYTHON_INCLUDE_DIRS "/home/icml/miniconda3/envs/DL/include/python3.8")
set(NUMPY_INCLUDE_DIR "/home/icml/miniconda3/envs/DL/lib/python3.8/site-packages/numpy/core/include")
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIR})
link_directories("/home/icml/miniconda3/envs/DL/lib/python3.8/config-3.8-x86_64-linux-gnu")
set(PYTHON_LIBRARIES "/home/icml/miniconda3/envs/DL/lib/libpython3.8.so")
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})

find_package(OpenCV REQUIRED)
message(STATUS "OpenCV library status:")
message(STATUS "  config: ${OpenCV_DIR}")
message(STATUS "  version: ${OpenCV_VERSION}")
message(STATUS "  libraries: ${OpenCV_LIBS}")
message(STATUS "  include path: ${OpenCV_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME}  ${OpenCV_LIBS})

目录结构
在这里插入图片描述
运行
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/392169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于 Rainbond 的 Pipeline(流水线)插件

背景 Rainbond 本身具有基于源码构建组件的能力&#xff0c;可以将多种编程语言的代码编译成 Docker 镜像&#xff0c;但是在持续集成的过程中&#xff0c;往往会需要对提交的代码进行静态检查、构建打包以及单元测试。之前由于 Rainbond 并没有 Pipeline 这种可编排的机制&am…

Git-学习笔记02【Git连接远程仓库】

Java后端 学习路线 笔记汇总表【黑马-传智播客】Git-学习笔记01【Git简介及安装使用】Git-学习笔记02【Git连接远程仓库】Git-学习笔记03【Git分支】目录 01-使用github创建一个远程仓库 02-推送到远程仓库介绍 03-创建ssh密钥及在github上配置公钥 04-使用ssh方式将本地仓…

MySQL基本查询

文章目录表的增删查改Create&#xff08;创建&#xff09;单行数据 全列插入多行数据 指定列插入插入否则更新替换Retrieve&#xff08;读取&#xff09;SELECT列全列查询指定列查询查询字段为表达式查询结果指定别名结果去重WHERE 条件基本比较BETWEEN AND 条件连接OR 条件连…

SpringBoot With IoC,DI, AOP,自动配置

文章目录1 IoC&#xff08;Inverse Of Controller&#xff09;2 DI&#xff08;Dependency Injection&#xff09;3 AOP&#xff08;面向切面编程&#xff09;3.1 什么是AOP&#xff1f;3.2 AOP的作用&#xff1f;3.3 AOP的核心概念3.4 AOP常见通知类型3.5 切入点表达式4 自动配…

计算机网络的166个概念 你知道几个第七部分

计算机网络传输层 可靠数据传输&#xff1a;确保数据能够从程序的一端准确无误的传递给应用程序的另一端。 容忍丢失的应用&#xff1a;应用程序在发送数据的过程中可能会存在数据丢失的情况。 非持续连接&#xff1a;每个请求/响应会对经过不同的连接&#xff0c;每一个连接…

vue3+ts:约定式提交(git husky + gitHooks)

一、背景 Git - githooks Documentation https://github.com/typicode/husky#readme gitHooks: commit-msg_snowli的博客-CSDN博客 之前实践过这个配置&#xff0c;本文在vue3 ts 的项目中&#xff0c;再记录一次。 二、使用 2.1、安装 2.1.1、安装husky pnpm add hus…

python学习——【第三弹】

前言 上一篇文章 python学习——【第二弹】中学习了python中的运算符内容&#xff0c;这篇文章接着学习python中的流程控制语句。 流程控制指的是代码运行逻辑、分支走向、循环控制&#xff0c;是真正体现我们程序执行顺序的操作。流程控制一般分为顺序执行、条件判断和循环控…

从源码的角度告诉你 spark是怎样完成对文件切片

目录 1.说明 2.怎样设置默认切片数 2.1 RDD默认切片设置 2.2 SparkSQL默认切片设置 3. makeRDD 切片原理 4. textFile 切片原理 4.1 切片规则 4.2 怎样设置切片大小 4.3 测试代码 5.hadoopFile 切片原理 5.1 说明 5.2 切片规则 5.3 怎样设置切片大小 5.4 代码测试…

【算法经典题集】前缀和与数学(持续更新~~~)

&#x1f63d;PREFACE&#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐ 评论&#x1f4dd;&#x1f4e2;系列专栏&#xff1a;算法经典题集&#x1f50a;本专栏涉及到的知识点或者题目是算法专栏的补充与应用&#x1f4aa;种一棵树最好是十年前其次是现在前缀和一维前缀和k倍…

【我的Android开发】AMS中Activity栈管理

概述 Activity栈管理是AMS的另一个重要功能&#xff0c;栈管理又和Activity的启动模式和startActivity时所设置的Flag息息相关&#xff0c;Activity栈管理的主要处理逻辑是在ActivityStarter#startActivityUnchecked方法中&#xff0c;本文也会围绕着这个方法进进出出&#xf…

Gopro卡无法打开视频恢复方法

下边来看一个文件系统严重受损的Gopro恢复案例故障存储: 120G SD卡故障现象:客户正常使用&#xff0c;备份数据时发现卡无法打开&#xff0c;多次插拔后故障依旧。故障分析:Winhex查看发现0号分区表扇区正常&#xff0c;这应该是一个exfat格式的文件系统&#xff0c;但是逻辑盘…

【单目3D目标检测】MonoDDE论文精读与代码解析

文章目录PrefacePros and ConsAbstractContributionsPreliminaryDirect depth estimationDepth from heightPespective-n-point&#xff08;PnP&#xff09;PipelineDiverse Depth EstimationsRobust Depth CombinationOutput distributionSelecting and combining reliable de…

JVM-从熟悉到精通

JVM 机器语言 一个指令由操作码和操作数组成 方法调用等于一个压栈的过程 栈有 BP寄存器 和 SP寄存器来占用空间 BP -> Base Point 栈基址&#xff08;栈底&#xff09;SP -> Stack Point 栈顶 字节序用于规定数据在内存单元如何存放&#xff0c;二进制位的高位和低…

计算机组成原理|第二章(笔记)

目录第二章 计算机的发展及应用2.1 计算机的发展史2.1.1 计算机的生产和发展2.1.2 微型计算机的出现和发展2.1.3 软件技术的兴起与发展2.2 计算机的应用2.3 计算机的展望上篇&#xff1a;第一章&#xff1a;计算机系统概论 第二章 计算机的发展及应用 2.1 计算机的发展史 2.1.…

基于半车悬架的轴距预瞄与轴间预瞄仿真对比

目录 前言 1. 半车悬架模型 2.轴距预瞄(单点预瞄)和轴间预瞄(两点预瞄)原理与仿真分析 2.1轴距预瞄(单点预瞄) 2.1.1预瞄原理 2.2.轴间预瞄(两点预瞄) 2.2.1预瞄原理 2.3仿真分析 3.总结 前言 对于悬架而言&#xff0c;四个车轮实际的输入信息是受到前后延时以及左右相…

SpringCloud:Feign的使用及配置

目录 Feign的使用及配置 1、Feign替代RestTemplate 2、使用Fegin步骤 3、自定义配置 4、Feign使用优化 5、Feign的最佳实践方式 Feign的使用及配置 1、Feign替代RestTemplate RestTemplate方式远程调用的问题 问题&#xff1a; 1、代码可读性差&#xff0c;编程体验不同…

HTML基本概述

文章目录网站和网页浏览器的作用HTML标签元素注释乱码问题web系统是以网站形式呈现的&#xff0c;而前端是以网页形式呈现的。 网站和网页 网站&#xff08;web site&#xff09;&#xff1a;互联网上用于展示特定内容的相关网页的集合。也就是说&#xff0c;一个网站包含多个…

【预告】ORACLE Primavera P6 v22.12 虚拟机发布

引言 离ORACLE Primavera P6 EPPM最新系统 v22.12已过去了3个多月&#xff0c;应盆友需要&#xff0c;也为方便大家体验&#xff0c;我近日将构建最新的P6的虚拟环境&#xff0c;届时将分享给大家&#xff0c;最终可通过VMWare vsphere (esxi) / workstation 或Oracle virtua…

SQL 窗口函数详解

SQL窗口函数详解 窗口函数的主要作用是对数据进行分组排序、求和、求平均值、计数等。 一、窗口函数的基本语法 <分析函数> OVER ([PARTITION BY <列清单>] ORDER BY <排序用列清单> [ROWS BETWEEN 开始位置 AND 结束位置])理解窗口函数的基本语法&#xff…

opencv校正图像

目录1、前言2、例程2.1、代码2.2、效果口罩说明书网页3、按步骤分析转灰度图降噪 Canny边缘检测膨胀&#xff08;可视具体情况省略&#xff09;轮廓检索选取角度1、前言 我们用相机拍照时&#xff0c;会因为角度问题造成拍歪&#xff0c;会影响图像的识别&#xff0c;这时就需…