本篇中使用的各软件的版本:
Ubuntu版本:18.04
LibTorch版本:1.9.1 + CUDA11.1
OpenCV版本:4.5.3(比较重要,版本不一样可能会不支持网络中的某些操作)
onnxruntime c++版本:1.8.0
第一步:导出ONNX模型
首先,安装所需要的包。
pip install onnx
pip install onnxruntime
接着,根据自己的需求训练网络,使用的Deeplab V3+源码下载自GitHub - bubbliiiing/deeplabv3-plus-pytorch: 这是一个deeplabv3-plus-pytorch的源码,可以用于训练自己的模型。
训练完成后,将predict.py中第26行的mode设置为"export_onnx",70行可以设置onnx模型的保存路径。将deeplab.py中的model_path设置为训练好的模型,再执行predict.py,就可以得到相应的onnx模型。
最后,使用Netron检查保存下来的onnx模型。
第二步:安装LibTorch
下载地址为:Start Locally | PyTorch
根据自己需要的版本,可以对官方提供的下载链接进行修改,例如pytorch 1.9.1+cuda 11.1的release版本的链接就是
https://download.pytorch.org/libtorch/cu111/libtorch-win-shared-with-deps-1.9.1%2Bcu111.zip
下载后解压即可。
第三步:安装OpenCV
首先,克隆源码。
git clone -b 4.5.3 https://gitee.com/opencv/opencv.git
cd opencv
git clone -b 4.5.3 https://gitee.com/opencv/opencv_contrib.git
接着,安装依赖项。
sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
sudo apt-get install build-essential qt5-default ccache libv4l-dev libavresample-dev libgphoto2-dev libopenblas-base libopenblas-dev doxygen openjdk-8-jdk pylint libvtk6-dev
sudo apt-get install pkg-config
最后,编译源码并安装。
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules ..
make
sudo make install
第四步:安装c++ onnxruntime
首先,克隆源码并检查版本。
git clone --recursive https://github.com/Microsoft/onnxruntime
cd onnxruntime/
git checkout v1.8.0
接着,编译源码,CUDA的路径根据自己实际情况修改。
./build.sh --skip_tests --use_cuda --config Release --build_shared_lib --parallel --cuda_home /usr/local/cuda-11.1 --cudnn_home /usr/local/cuda-11.1
最后 ,编译成功。
第五步:编写c++代码
mkdir deeplab_v3_plus_cpp
cd deeplab_v3_plus_cpp
创建onnx.cpp文件,代码如下。
#include "torch/script.h"
#include "torch/torch.h"
#include <iostream>
#include <vector>
#include <onnxruntime_cxx_api.h>
#include <opencv2/opencv.hpp>
#include <opencv2\imgproc\types_c.h>
using namespace std;
int main()
{
string mobileFile = "models.onnx";
string imageFile;
cout << "请输入图像文件名:";
cin >> imageFile;
cv::dnn::Net net = cv::dnn::readNetFromONNX(mobileFile);
cv::Mat imageBGR = cv::imread(imageFile, cv::ImreadModes::IMREAD_COLOR);
int w = imageBGR.cols;
int h = imageBGR.rows;
cv::Mat resizedImageRGB, resizedImage, preprocessedImage;
cv::resize(imageBGR, resizedImage, cv::Size(512, 512), cv::INTER_AREA);
cv::cvtColor(resizedImage, resizedImageRGB, cv::ColorConversionCodes::COLOR_BGR2RGB);
resizedImageRGB.convertTo(resizedImage, CV_32F, 1.0 / 255);
cv::Mat channels[3];
cv::split(resizedImage, channels);
cv::merge(channels, 3, resizedImage);
cv::dnn::blobFromImage(resizedImage, preprocessedImage);
net.setInput(preprocessedImage);
cv::Mat result = net.forward();
int size[3] = { result.size[1], result.size[2], result.size[3] };
cv::Mat output(3, size, CV_32F, result.ptr<float>());
auto output_tensor = torch::from_blob(output.data, {result.size[1], result.size[2], result.size[3]});
output_tensor = output_tensor.permute({ 1, 2, 0 });
output_tensor = torch::softmax(output_tensor, -1);
output_tensor = output_tensor.argmax(-1) * (255/(result.size[1]-1));
output_tensor = output_tensor.to(torch::kU8);
cv::Mat predict(512, 512, CV_8UC1, output_tensor.data_ptr<uchar>());
cv::resize(predict, predict, cv::Size(w, h), cv::INTER_AREA);
cv::imshow("分割图", predict);
cv::imwrite("分割图.jpg", predict);
return 0;
}
在同一文件夹下创建CMakeLists.txt,内容如下,需根据实际配置修改。
cmake_minimum_required(VERSION 3.21)
project(ONNX CXX)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS "-std=c++14 -mfma")
# Modify cmake module path if new .cmake files are required
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake")
## System dependencies are found with CMake's conventions
set(Torch_DIR /home/yanglab/libtorch-cxx11-abi-shared-with-deps-1.9.1+cu111/libtorch/share/cmake/Torch)
find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)
message("OpenCV version is: ${OpenCV_VERSION}")
message(STATUS "PyTorch status:")
message(STATUS "libraries: ${TORCH_LIBRARIES}")
###########
## Build ##
###########
set(ONNX_INCLUDE_DIR /home/yanglab/onnxruntime-linux-x64-gpu-1.8.0/include)
set(ONNX_LIB_DIR /home/yanglab/onnxruntime-linux-x64-gpu-1.8.0/lib)
include_directories(
${OpenCV_INCLUDE_DIRS}
${ONNX_INCLUDE_DIR}
)
add_executable(onnx onnx.cpp)
# 链接OpenCV库
target_link_libraries(onnx ${OpenCV_LIBS} ${TORCH_LIBRARIES}
${ONNX_LIB_DIR}/libonnxruntime.so
${ONNX_LIB_DIR}/libonnxruntime.so.1.8.0
${ONNX_LIB_DIR}/libonnxruntime_providers_cuda.so
${ONNX_LIB_DIR}/libonnxruntime_providers_shared.so)
编译代码,并运行可执行文件,即可看到效果。
mkdir build
cd build
cmake ..
make
./onnx