使用 C++ 编写支持多模型调用的动态连接库,将 yolov5的ONNX 模型加载进来,并编译生成dll与注释供其他程序使用
时间: 2023-11-22 18:56:08 浏览: 116
首先,要使用 C++ 编写支持多模型调用的动态连接库,需要使用一些库,比如 OpenCV 和 ONNX Runtime。以下是一个基本的示例代码:
```c++
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <onnxruntime_cxx_api.h>
class YOLOv5Detector {
public:
YOLOv5Detector(const std::string& model_path) {
// Initialize ONNX Runtime
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
Ort::SessionOptions session_options;
session_options.SetIntraOpNumThreads(1);
session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_BASIC);
session_ = std::make_unique<Ort::Session>(env, model_path, session_options);
// Get model input and output information
auto input_info = session_.get()->GetInputTypeInfo(0);
auto output_info = session_.get()->GetOutputTypeInfo(0);
input_name_ = input_info.GetOnnxName();
output_name_ = output_info.GetOnnxName();
input_dims_ = input_info.GetTensorTypeAndShapeInfo().GetShape();
output_dims_ = output_info.GetTensorTypeAndShapeInfo().GetShape();
}
std::vector<cv::Rect> detect(const cv::Mat& image) {
// Preprocess image
cv::Mat resized_image;
cv::resize(image, resized_image, cv::Size(input_dims_[3], input_dims_[2]));
cv::Mat float_image;
resized_image.convertTo(float_image, CV_32FC3, 1.0 / 255.0);
std::vector<float> input_data(float_image.ptr<float>(), float_image.ptr<float>() + float_image.total() * float_image.channels());
// Initialize input and output tensors
Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
std::vector<int64_t> input_shape = {1, 3, input_dims_[2], input_dims_[3]};
std::vector<int64_t> output_shape = {1, static_cast<int64_t>(output_dims_[1]), static_cast<int64_t>(output_dims_[2]), static_cast<int64_t>(output_dims_[3])};
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_data.data(), input_data.size(), input_shape.data(), input_shape.size());
Ort::Value output_tensor = Ort::Value::CreateTensor<float>(memory_info, nullptr, output_shape.data(), output_shape.size());
// Run inference
std::vector<const char*> input_names = {input_name_.c_str()};
std::vector<const char*> output_names = {output_name_.c_str()};
session_.get()->Run(Ort::RunOptions{nullptr}, input_names.data(), &input_tensor, 1, output_names.data(), 1, &output_tensor);
// Postprocess output
const float* output_data = output_tensor.GetTensorMutableData<float>();
std::vector<cv::Rect> detected_rects;
for (int i = 0; i < output_dims_[1]; i++) {
float score = output_data[5 * i + 4];
if (score >= 0.5) {
float x_center = output_data[5 * i];
float y_center = output_data[5 * i + 1];
float width = output_data[5 * i + 2];
float height = output_data[5 * i + 3];
int x_left = static_cast<int>((x_center - width / 2) * image.cols);
int y_top = static_cast<int>((y_center - height / 2) * image.rows);
int rect_width = static_cast<int>(width * image.cols);
int rect_height = static_cast<int>(height * image.rows);
detected_rects.emplace_back(x_left, y_top, rect_width, rect_height);
}
}
return detected_rects;
}
private:
std::unique_ptr<Ort::Session> session_;
std::string input_name_;
std::string output_name_;
std::vector<int64_t> input_dims_;
std::vector<int64_t> output_dims_;
};
```
此代码创建了一个名为 `YOLOv5Detector` 的类,该类使用 ONNX Runtime 加载 YOLOv5 模型,并在给定图像上运行检测。检测结果是矩形的列表,表示在图像中检测到的对象。
要将此类编译为 DLL,您需要使用 Visual Studio 或其他支持 Windows DLL 编译的 IDE。以下是一个示例项目文件:
```xml
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{GUID}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>YOLOv5Detector</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>false</WholeProgramOptimization>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>false</WholeProgramOptimization>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(OPENCV_DIR)\include;$(ONNXRUNTIME_DIR)\include;</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>Create</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<TreatWarningAsError>true</TreatWarningAsError>
<LanguageStandard>c++17</LanguageStandard>
</ClCompile>
<Link>
<AdditionalDependencies>onnxruntime.lib;opencv_world450d.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OPENCV_DIR)\x64\vc15\lib;$(ONNXRUNTIME_DIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>Create</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<TreatWarningAsError>true</TreatWarningAsError>
<LanguageStandard>c++17</LanguageStandard>
</ClCompile>
<Link>
<AdditionalDependencies>onnxruntime.lib;opencv_world450.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OPENCV_DIR)\x64\vc15\lib;$(ONNXRUNTIME_DIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="detector.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition=" '$(Configuration)|$(Platform)'=='Debug|Win32' ">Create</PrecompiledHeader>
<PrecompiledHeader Condition=" '$(Configuration)|$(Platform)'=='Release|Win32' ">Create</PrecompiledHeader>
</ClCompile>
<ClInclude Include="detector.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
```
将此项目文件保存为 `YOLOv5Detector.vcxproj`,然后使用 Visual Studio 打开该文件并构建解决方案。这将生成一个名为 `YOLOv5Detector.dll` 的 DLL 文件。您可以在其他 C++ 程序中使用此 DLL 文件,并调用 `YOLOv5Detector` 类来运行目标检测算法。
阅读全文