VTM中直接调用python(pytorch模型)

本文详细介绍了如何在C++程序中调用Python文件,特别是包含第三方库如PyTorch的神经网络模型。首先配置C++环境,包括包含目录和库目录设置。接着在C++代码中,通过`Py_Initialize`和`Py_Finalize`初始化和结束Python环境,使用`PyImport_ImportModule`导入Python模块,通过`PyObject_CallObject`调用Python函数,并将C++的一维list传递给Python,最后从Python返回结果并处理。在Python端,加载模型并进行预测,将结果转换为一维list返回。文章还提到了在不同设备间测试时遇到的问题及其解决方案。
部署运行你感兴趣的模型镜像

参考:

​​​​​​C++调用python文件(包含第三方库) - 知乎 (zhihu.com)

奇巧:C++ 调用python方法 - 知乎 (zhihu.com)

(31条消息) C调用Python(传递数字、字符串、list数组(一维、二维),结构体)_sunshine_9990的博客-优快云博客

一、环境配置:

一、VC++目录:

1、包含目录:python所在文件夹下include文件夹“C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\include”

2、库目录:python所在文件夹下libs文件夹“C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\libs”

 二、链接器输入

附加依赖项:python37.lib

三、release文件夹(同EncoderApp.exe文件夹)

复制python文件夹下DLLs、libs、Lib文件夹、所调用的python文件、python37.lib到该文件夹下

测试所用的.bat、.cfg也放在该文件夹下

 

二、C++代码,传递一维list[[list0],[list1],[list2]],返回值一维list

int main(int argc, char* argv[])
{
  //add
  Py_Initialize();
  //end
  // print information
  fprintf( stdout, "\n" );
  fprintf( stdout, "VVCSoftware: VTM Encoder Version %s ", VTM_VERSION );
  fprintf( stdout, NVM_ONOS );
  fprintf( stdout, NVM_COMPILEDBY );
  fprintf( stdout, NVM_BITS );
      ....
      ....
      ....
  return 0;
  //add
  Py_Finalize();
  //end
}
void EncCu::python()
{

  //初始化使用的变量
  PyObject* pModule = NULL;
  PyObject* pFunc = NULL;
  PyObject* pName = NULL;
  PyObject* pReturn = NULL;
  int wh = width * height;

  //2、初始化python系统文件路径,保证可以访问到 .py文件
  PyRun_SimpleString("import sys");
  PyRun_SimpleString("sys.path.append('./')");
  //3、导入所调用的python文件
  pModule = PyImport_ImportModule("GEAPI");
  //4、调用python文件函数
  pFunc = PyObject_GetAttrString(pModule, "out");
  //5、定义三个Pylist列表
  PyObject* PyListP0 = PyList_New(wh);
  PyObject* PyListP1 = PyList_New(wh);
  PyObject* PyListP2 = PyList_New(wh);

  int num = 0;
  for (unsigned y = 0; y < height; y++)
  {
    for (unsigned x = 0; x < width; x++)
    {
      Pel pixel = (pcYuvSrc0.bufs[0].at(x, y) + IF_INTERNAL_OFFS) >> IF_INTERNAL_FRAC_BITS(ClipBD);
      float pixelL0 = float(round(float(pixel) / 4.0)); 
      //向列表中添加元素
      PyList_SetItem(PyListP0, num, PyFloat_FromDouble(pixelL0));
      num++;
    }
    //cout << endl;
  }
  //PylistP1、PylistP2同理
  //...
  //6、三个list添加到一个新list中
  PyObject* PyList = PyList_New(0);
  PyList_Append(PyList, PyListP0);
  PyList_Append(PyList,PyListP1);
  PyList_Append(PyList, PyListP2);
  //7、定义一个Tuple对象,Tuple对象的长度与Python函数参数个数一致
  PyObject* ArgList = PyTuple_New(1);
  //8、传递list到python函数中
  PyTuple_SetItem(ArgList, 0, PyList);
  //9、接收返回值list
  pReturn = PyObject_CallObject(pFunc, ArgList);
  for (unsigned y = 0; y < height; y++)
    {
      for (unsigned x = 0; x < width; x++)
      {
        PyObject* Item = PyList_GetItem(pReturn, num);//获取List对象中的每一个元素
        num++;
        float result;
        PyArg_Parse(Item, "f", &result);//f表示转换成float型变量
        Pel pixel = round(result);
        pcYuvdst.bufs[0].at(x, y) = Pel(pixel * 4);
        Py_DECREF(Item);

      }
      //cout << endl;
    }
}

三、c++调用python完整代码,神经网络pytorch模型

import sys
import torch
import torch.nn as nn
import torch.nn.functional as F
import os
import numpy as np
from pure_network import DetailEnhance
def out(inputorg):
  #inputorg = [[list0],[list1],[list2]]
  inputP0 = inputorg[0]
  inputP1 = inputorg[1]
  inputP2 = inputorg[2]
  #模型加载
  model = DetailEnhance()
  model = torch.load("",map_location='cpu')
  model.eval()
  #输入转tensor,转数组
  P0 = torch.as_tensor(inputP0,dtype=torch.float32)
  P1 = torch.as_tensor(inputP1,dtype=torch.float32)
  P2 = torch.as_tensor(inputP2,dtype=torch.float32)

  refP0 = np.array(P0).reshape(height,width)
  refP1 = np.array(P1).reshape(height, width)
  refP2 = np.array(P2).reshape(height, width)
  input0 = np.array([[refP0], [refP1], [refP2]])
  
  #增减维度,确保与模型输入维度一致
  input = (torch.from_numpy(input0).unsqueeze(0) / 255)
  output = model(input)*255
  #输出转list,返回一维list[]
  out = output.detach().numpy().reshape(1,width*height).tolist()
  dst = out[0]
  return dst

踩坑记录:

1、c++中调用python

//PyObject* Item 写在循环外,否则无法调用大块
PyObject* Item = NULL;  
for (unsigned y = 0; y < height; y++)
    {
      for (unsigned x = 0; x < width; x++)
      {
        Item = PyList_GetItem(pReturn, num);//获取List对象中的每一个元素
        num++;
        float result;
        PyArg_Parse(Item, "f", &result);//f表示转换成float型变量
        Pel pixel = round(result);
        pcYuvdst.bufs[0].at(x, y) = Pel(pixel * 4);


      }
      //cout << endl;
    }
Py_DECREF(Item);

2、换设备测试,复制release文件,其中Lib文件夹使用新设备环境下Lib文件夹

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

### 使用Python实现图像压缩VTM并解决glymur库中OpenJPEG版本过低的问题 #### 解决glymur库中OpenJPEG版本过低的问题 glymur库在写入JP2文件时需要依赖至少2.3.0版本的OpenJPEG库[^1]。如果系统中安装的OpenJPEG版本低于此要求,则会抛出`RuntimeError: OpenJPEG version 2.3.0 required to write images`错误。 为了解决这一问题,可以按照以下方法升级OpenJPEG: - **Linux系统**: 在基于Debian的系统(如Ubuntu)上,可以通过以下命令安装或升级到最新版本的OpenJPEG: ```bash sudo apt-get update sudo apt-get install libopenjp2-7 libopenjp2-7-dev ``` 如果默认软件源中的OpenJPEG版本仍低于2.3.0,则需要从源代码编译安装更高版本的OpenJPEG[^2]。 - **Windows系统**: Windows用户需要手动下载并编译OpenJPEG源代码。具体步骤如下: 1. 下载OpenJPEG源代码:[https://github.com/uclouvain/openjpeg](https://github.com/uclouvain/openjpeg) 2. 安装CMake工具:[https://cmake.org/download/](https://cmake.org/download/) 3. 使用CMake生成适用于MSVC的项目文件,并完成编译。 4. 将编译后的动态链接库路径添加到系统的环境变量`PATH`中。 - **macOS系统**: macOS用户可以通过Homebrew安装最新版本的OpenJPEG: ```bash brew install openjpeg ``` 配置glymur以识别更新后的OpenJPEG库可以通过设置环境变量`OPENJP2_DIR`指向OpenJPEG的安装路径来解决问题。例如,在Linux或macOS上运行以下命令: ```bash export OPENJP2_DIR=/path/to/openjpeg ``` #### Python实现图像压缩VTM VTM(VVC Test Model)是用于实现视频编码标准VVC(Versatile Video Coding)的参考软件。虽然VTM主要用于视频压缩,但也可以用于单帧图像的压缩。以下是使用Python调用VTM进行图像压缩的基本流程: 1. **安装FFmpeg和VTM**: 首先需要安装FFmpeg和VTM。FFmpeg用于将图像转换为YUV格式,而VTM则负责实际的压缩过程。 - 安装FFmpeg: ```bash sudo apt-get install ffmpeg ``` - 下载并编译VTM: ```bash git clone https://gitlab.com/etsi/vtm.git cd vtm make ``` 2. **编写Python脚本**: 使用Python调用FFmpeg和VTM进行图像压缩。以下是一个示例脚本: ```python import subprocess import os def convert_image_to_yuv(input_image, output_yuv): """ 使用FFmpeg将图像转换为YUV格式。 """ command = [ "ffmpeg", "-i", input_image, "-pix_fmt", "yuv420p", "-s", "1920x1080", # 设置分辨率 output_yuv ] subprocess.run(command, check=True) def compress_with_vtm(input_yuv, output_bitstream, config_file): """ 使用VTM对YUV图像进行压缩。 """ vtm_encoder_path = "/path/to/vtm/bin/TAppEncoderStatic" # 替换为VTM的实际路径 command = [ vtm_encoder_path, "-c", config_file, "-i", input_yuv, "-b", output_bitstream, "-q", "30" # 设置量化参数 ] subprocess.run(command, check=True) if __name__ == "__main__": input_image = "input.png" yuv_file = "output.yuv" bitstream_file = "output.bit" config_file = "encoder_intra_main_rext.cfg" # 替换为VTM的实际配置文件路径 # 转换图像为YUV格式 convert_image_to_yuv(input_image, yuv_file) # 使用VTM进行压缩 compress_with_vtm(yuv_file, bitstream_file, config_file) # 清理临时文件 os.remove(yuv_file) ``` 上述代码首先使用FFmpeg将输入图像转换为YUV格式,然后调用VTM对YUV数据进行压缩[^3]。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值