首页 > 系统相关 >在Linux中使用C++调用Python程序

在Linux中使用C++调用Python程序

时间:2024-09-03 11:04:37浏览次数:12  
标签:img Python dell C++ python env Linux home

为什么要用C++调Python

我们训练部署CNN模型时,服务器用Pytorch测试的精度比我们部署端精度高0.5%。经过多方排查,发现是由于Pytorch预处理图片使用PIL进行图片读取和尺寸调整,但是部署端采用OpenCV进行图片读取和尺寸调整。两种实现方式实现的Resize操作差异非常大。为了快速完成项目,暂时用C++调用Python的PIL库进行图像预处理,检查实现的精度。

安装Python环境

因为C在编译的时候需要链接到Python函数的一些链接库,并且Linux环境下更改默认Python可能会造成桌面系统损坏,所以我们重新编译了一个Python环境。

1. 安装Python所需的依赖项sudo apt install libbz2-dev

2. 下载Python源代码:https://www.python.org/ftp/python/3.10.14/Python-3.10.14.tgz

3. 新建python_env目录,并将tgz压缩包复制到其中,使用tar -xvf Python-3.10.14.tgz 解压该文件,得到如下目录结构:

python_env|

| Python-3.10.14

| Python-3.10.14.tgz

4.cd Python-3.10.14

5.配置Python安装文件,打开--enable-shared生成可以连接到g++的动态链接库文件,使用—prefix指定安装目录:

./configure --enable-shared --prefix=/home/dell/Work4/workspace/user_work4/python_env

6.make

7.make -j16 install

8.此时所需的Python环境已经安装到/home/dell/Work4/workspace/user_work4/python_env目录下

9.安装成功后会显示需要添加动态链接库的位置:LD_LIBRARY_PATH

10.将之前显示的动态链接库路径添加到环境变量(可以放到~/.bashrc下):

export LD_LIBRARY_PATH=/home/dell/Work4/workspace/user_work4/python_env/Python-3.10.14

安装Pytorch OpenCV

在对应的python环境下安装pytorch:

/home/dell/Work4/workspace/user_work4/python_env/bin/python3 -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

在对应的python环境下安装opencv:

/home/dell/Work4/workspace/user_work4/python_env/bin/python3 -m pip install opencv-python

编写Python脚本

编写Python脚本pil_load_pic_mod.py

from PIL import Image
import os
import cv2
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import numpy as np
import torchvision.transforms as transforms
import pdb

def pil_load_pic(img_path):
    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    trans=transforms.Compose([transforms.Resize(256),transforms.CenterCrop(224),transforms.ToTensor(),normalize])

    # PIL Loading PIC
    # img = Image.open(img_path)
    # img_rgb = img.convert('RGB')

    # Opencv Loading PIC
    img = cv2.imread(img_path)
    img_rgb = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    img_rgb = Image.fromarray(img_rgb)

    # Resize
    img_resized = trans(img_rgb)
    img_numpy = img_resized.numpy()

    # pdb.set_trace()
    # print("Python Successfully load %s"%img_path) #dtype=float32
    return img_numpy.reshape(-1).tolist()

if __name__=="__main__":
    print(pil_load_pic("/home/dell/Work3/data_set/ImageNet/ILSVRC2012_img_val/ILSVRC2012_val_00000001.JPEG"))

#234
#!/home/dell/Disk03/students/user/python_env/bin/python3
#112
#!/home/dell/Disk03/user/python_env/bin/python3

编写C++程序

#include<stdio.h>
#include<Python.h>

int main(){
    // PIL load and resize pic Init
    float mean[3]={0.485, 0.456, 0.406}, std[3]={0.229, 0.224, 0.225}; //rgb
    #define PIC_OUT_SIZE 224
    Py_Initialize();
    if (!Py_IsInitialized()) {
        printf("ERROR: Python init fail\n");
        exit(1);
    }
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");
    PyObject *pModule = PyImport_ImportModule("pil_load_pic_mod");
    if (pModule == NULL){
        printf("ERROR: No Python module loaded!\n");
        PyErr_Print();
        exit(1);
    }

    PyObject *pFunc = PyObject_GetAttrString(pModule, "pil_load_pic");
    if (!PyCallable_Check(pFunc)){
        printf("ERROR: No Python module loaded!\n");
        PyErr_Print();
        exit(1);
    }

    char picture_file_path[255] = {0};
    char *img_resized;
    img_resized = (char *)malloc(PIC_OUT_SIZE*PIC_OUT_SIZE*3);
    for (int pic_num = 1; pic_num <=1; pic_num++){

        sprintf(picture_file_path, "/home/dell/Work4/workspace/user_work4/c_and_python/ILSVRC2012_val_%08d.JPEG", pic_num);

        // OpenCV load and resize pic
        // cv_load_pic(picture_file_path,img_resized);

        // PIL load and resize pic
        PyObject *loadImageArgs = Py_BuildValue("(s)", picture_file_path);
        PyObject *pValue = PyObject_CallObject(pFunc, loadImageArgs);
        Py_DECREF(loadImageArgs);

        if (pValue != NULL) {
            printf("Python Successfully load %s\n",picture_file_path);
            if (PyList_Check(pValue)) {
                Py_ssize_t size = PyList_Size(pValue);
                if(size != (PIC_OUT_SIZE*PIC_OUT_SIZE*3)){
                    printf("PIL output pic size error!\n");
                    exit(1);
                }
                int row=0, col=0, cc=0, out_idx=0;
                for (Py_ssize_t i = 0; i < size; i++) {
                    PyObject *item = PyList_GetItem(pValue, i);

                    // if(col<3 && row<3){
                    //     printf("col:%d row:%d cc:%d %f\n", col, row, cc, PyFloat_AsDouble(item));
                    // }
                    img_resized[out_idx++] = (PyFloat_AsDouble(item) * std[cc] + mean[cc]) * 255;

                    if(cc==3-1 && row==PIC_OUT_SIZE-1 && col==PIC_OUT_SIZE-1){
                        cc = 0;
                    }
                    else if(row==PIC_OUT_SIZE-1 && col==PIC_OUT_SIZE-1){
                        cc++;
                    }

                    if(row==PIC_OUT_SIZE-1 && col==PIC_OUT_SIZE-1){
                        row = 0;
                    }
                    else if(col==PIC_OUT_SIZE-1){
                        row++;
                    }

                    if(col==PIC_OUT_SIZE-1){
                        col = 0;
                    }
                    else{
                        col++;
                    }
                }
            }
            Py_DECREF(pValue);
        } else {
            PyErr_Print();
        }
    }
    return 0;
}

 

编写Makefile

输入指令查看所需编译参数:

/home/dell/Work4/workspace/user_work4/python_env/bin/python3-config --cflags --embed

输入指令查看所需链接参数:

# /home/dell/Work4/workspace/user_work4/python_env/bin/python3-config --ldflags --embed

最终编写Makefile:

# /home/dell/Work4/workspace/user_work4/python_env/bin/python3-config --cflags --embed
COMPILE_FLAG = -I/home/dell/Work4/workspace/user_work4/python_env/include/python3.10 -I/home/dell/Work4/workspace/user_work4/python_env/include/python3.10  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall

# /home/dell/Work4/workspace/user_work4/python_env/bin/python3-config --ldflags --embed
LINK_FLAG = -L/home/dell/Work4/workspace/user_work4/python_env/lib -lpython3.10 -lcrypt -lpthread -ldl  -lutil -lm -lm

.PHONY: host

host: main_c.o
    gcc main_c.o -o run.exe $(LINK_FLAG)

main_c.o: main_c.cpp
    gcc main_c.cpp -c -o main_c.o $(COMPILE_FLAG)

 

标签:img,Python,dell,C++,python,env,Linux,home
From: https://www.cnblogs.com/Dee-sir/p/18394146

相关文章

  • windows C++ 并行编程-并发的异常处理(三)
    并发运行时使用C++异常处理来传达多种错误。这些错误包括:无效使用运行时、无法获取资源等运行时错误,以及你提供给任务和任务组的工作函数中发生的错误。当任务或任务组引发异常时,运行时会保存该异常并将其编组到等待任务或任务组完成的上下文。对于轻量级任务和代理等组件......
  • 【最新原创毕设】基于微信小程序的老年人健康医疗信息服务平台设计+24246(免费领源码)可
    摘 要老年人健康是社会关注的重点之一,随着我国人口老龄化程度的增加,老年人的健康问题逐渐凸显。为了更好地满足老年人的健康需求,提高医疗服务质量和效率,开发一个基于SpringBoot的老年人健康医疗信息服务平台是十分必要的。老年人健康医疗信息服务平台利用Java语言,通过spring......
  • windows C++ 并行编程-并发的异常处理(二)
    并发运行时使用C++异常处理来传达多种错误。这些错误包括:无效使用运行时、无法获取资源等运行时错误,以及你提供给任务和任务组的工作函数中发生的错误。当任务或任务组引发异常时,运行时会保存该异常并将其编组到等待任务或任务组完成的上下文。对于轻量级任务和代理等组件......
  • C++学习笔记(四)类和对象
    类和对象C++对象模型和this指针成员变量和成员函数的存储C++中的成员变量和成员函数是分开存储的,只有非静态成员变量才属于类的对象上classPerson{intm_Age;//非静态成员变量staticintm_B;//静态成员变量voidfunc(){//不属于类的对象上}staticv......
  • 拒绝做工具小子—编写Python漏洞验证脚本_编写漏洞利用脚本
    前言我们实战经常会遇到以下几个问题:​1、遇到一个利用步骤十分繁琐的漏洞,中间错一步就无法利用​2、挖到一个通用漏洞,想要批量刷洞小赚一波,但手动去测试每个网站工作量太大这个时候编写一个poc脚本将会将会减轻我们很多工作。本文将以编写一个高效通用的poc脚本为目......
  • (免费源码)计算机毕业设计必看必学 原创定制程序 java、PHP、python、小程序、文案全套
    目 录摘要1绪论1.1研究背景1.2研究意义1.3论文结构与章节安排2 自助洗衣房管理系统系统分析2.1可行性分析2.2系统流程分析2.2.1数据增加流程2.2.2数据修改流程2.2.3数据删除流程2.3系统功能分析2.3.1功能性分析2.3.2非功能性分析......
  • c++入门基础
    欢迎来到c++入门基础的学习目录1、第一个c++程序2、命名空间3、c++的输入与输出4、缺省参数5、函数重载6、详解引用(引用属于重点知识)7、指针与引用的差别8、内联函数9、nullptr在学习c++之前我们要知道c++是什么—c++是c语言的扩展,主要在c语言之上添加了封装、继......
  • 10 Python面向对象编程:类和对象以及和Java的对比
    本篇是Python系列教程第10篇,更多内容敬请访问我的Python合集这里只介绍类和对象,self、属性、方法、访问控制、类继承、方法重写在后面的文章里介绍在Python中,类和对象是面向对象编程的基础。1类的概念类是一种创建对象的蓝图或模板。它定义了一组属性(变量)和方法(函......
  • 11 Python面向对象编程:三大特性,封装、继承、多态
    本篇是Python系列教程第11篇,更多内容敬请访问我的Python合集1封装封装就是把类的公有属性改成私有属性,并且提供对外访问的方法。示例classMyClass:def__init__(self,value):self.__value=valuedefget_value(self):returnself.__......
  • Python-openpyxl读取Excel中数据写入MySQL的表中
     Python代码:importpymysqlfromopenpyxlimportload_workbookdefinsert_excel_data_to_mysql(in_filename,in_host,in_user,in_password,in_database,in_table):#连接数据库mydb=pymysql.connect(host=in_host,#数据库主机地址......