【TensorRT】TensorRT C# API 项目更新 (1):支持动态Bath输入模型推理(下篇)

4. 接口应用

关于该项目的调用方式在上一篇文章中已经进行了详细介绍,具体使用可以参考《最新发布!TensorRT C# API :基于C#与TensorRT部署深度学习模型》,下面结合Yolov8-cls模型详细介绍一下更新的接口使用方法。

4.1 创建并配置C#项目

首先创建一个简单的C#项目,然后添加项目配置。

首先是添加TensorRT C# API 项目引用,如下图所示,添加上文中C#项目生成的dll文件即可。

接下来添加OpenCvSharp,此处通过NuGet Package安装即可,此处主要安装以下两个程序包即可:

|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| | |

配置好项目后,项目的配置文件如下所示:

xml 复制代码
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>TensorRT_CSharp_API_demo</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="OpenCvSharp4.Extensions" Version="4.9.0.20240103" />
    <PackageReference Include="OpenCvSharp4.Windows" Version="4.9.0.20240103" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="TensorRtSharp">
      <HintPath>E:\GitSpace\TensorRT-CSharp-API\src\TensorRtSharp\bin\Release\net6.0\TensorRtSharp.dll</HintPath>
    </Reference>
  </ItemGroup>

</Project>

4.2 添加推理代码

此处演示一个简单的图像分类项目,以Yolov8-cls项目为例:

(1) 转换engine模型

动态输入的模型在进行格式转换时,需要指定模型推理形状至此的范围,minShapes表示模型推理支持的最小形状,optShapes表示模型推理支持的最佳形状,maxShapes表示模型推理支持的最大形状,模型转换需要消耗较多时间,最终转换成功后会在模型同级目录下生成相同名字的.engine文件。

csharp 复制代码
Dims minShapes = new Dims(1, 3, 224, 224);
Dims optShapes = new Dims(10, 3, 224, 224);
Dims maxShapes = new Dims(20, 3, 224, 224);
Nvinfer.OnnxToEngine(onnxPath, 20, "images", minShapes, optShapes, maxShapes);
(2) 定义模型预测方法

下面代码是定义的Yolov8-cls模型的预测方法,该方法支持动态Bath输入模型推理,可以根据用户输入图片数量,自动设置输入Bath,然后进行推理。

下面代码与上一篇文章中的代码差异主要是增加了predictor.SetBindingDimensions("images", new Dims(batchNum, 3, 224, 224));这一句代码。同时在初始化时,设置最大支持20Bath,这与上文模型转换时设置的一致。

csharp 复制代码
public class Yolov8Cls
{
    public Dims InputDims;
    public int BatchNum;
    private Nvinfer predictor;
    public Yolov8Cls(string enginePath)
    {
        predictor = new Nvinfer(enginePath, 20);
        InputDims = predictor.GetBindingDimensions("images");
    }
    public void Predict(List<Mat> images)
    {
        BatchNum = images.Count;
        for (int begImgNo = 0; begImgNo < images.Count; begImgNo += BatchNum)
        {
            DateTime start = DateTime.Now;
            int endImgNo = Math.Min(images.Count, begImgNo + BatchNum);
            int batchNum = endImgNo - begImgNo;
            List<Mat> normImgBatch = new List<Mat>();
            int imageLen = 3 * 224 * 224;
            float[] inputData = new float[BatchNum * imageLen];
            for (int ino = begImgNo; ino < endImgNo; ino++)
            {
                Mat input_mat = CvDnn.BlobFromImage(images[ino], 1.0 / 255.0, new OpenCvSharp.Size(224, 224), 0, true, false);
                float[] data = new float[imageLen];
                Marshal.Copy(input_mat.Ptr(0), data, 0, imageLen);
                Array.Copy(data, 0, inputData, ino * imageLen, imageLen);
            }
            predictor.SetBindingDimensions("images", new Dims(batchNum, 3, 224, 224));
            predictor.LoadInferenceData("images", inputData);
            DateTime end = DateTime.Now;
            Console.WriteLine("[ INFO ] Input image data processing time: " + (end - start).TotalMilliseconds + " ms.");
            predictor.infer();
            start = DateTime.Now;
            predictor.infer();
            end = DateTime.Now;
            Console.WriteLine("[ INFO ] Model inference time: " + (end - start).TotalMilliseconds + " ms.");
            start = DateTime.Now;

            float[] outputData = predictor.GetInferenceResult("output0");
            for (int i = 0; i < batchNum; ++i)
            {
                Console.WriteLine(string.Format("[ INFO ] Classification Top {0} result : ", 2));
                float[] data = new float[1000];
                Array.Copy(outputData, i * 1000, data, 0, 1000);
                List<int> sortResult = Argsort(new List<float>(data));
                for (int j = 0; j < 2; ++j)
                {
                    string msg = "";
                    msg += ("index: " + sortResult[j] + "\t");
                    msg += ("score: " + data[sortResult[j]] + "\t");
                    Console.WriteLine("[ INFO ] " + msg);
                }
            }
            end = DateTime.Now;
            Console.WriteLine("[ INFO ] Inference result processing time: " + (end - start).TotalMilliseconds + " ms.\n");
        }
    }
    public static List<int> Argsort(List<float> array)
    {
        int arrayLen = array.Count;
        List<float[]> newArray = new List<float[]> { };
        for (int i = 0; i < arrayLen; i++)
        {
            newArray.Add(new float[] { array[i], i });
        }
        newArray.Sort((a, b) => b[0].CompareTo(a[0]));
        List<int> arrayIndex = new List<int>();
        foreach (float[] item in newArray)
        {
            arrayIndex.Add((int)item[1]);
        }
        return arrayIndex;
    }
}
(3) 预测方法调用

下面是上述定义的预测方法,为了测试不同Bath性能,此处读取了多张图片,并分别预测不同张数图片,如下所示:

csharp 复制代码
Yolov8Cls yolov8Cls = new Yolov8Cls("E:\\Model\\yolov8\\yolov8s-cls_b.engine");
Mat image1 = Cv2.ImRead("E:\\ModelData\\image\\demo_4.jpg");
Mat image2 = Cv2.ImRead("E:\\ModelData\\image\\demo_5.jpg");
Mat image3 = Cv2.ImRead("E:\\ModelData\\image\\demo_6.jpg");
Mat image4 = Cv2.ImRead("E:\\ModelData\\image\\demo_7.jpg");
Mat image5 = Cv2.ImRead("E:\\ModelData\\image\\demo_8.jpg");

yolov8Cls.Predict(new List<Mat> { image1, image2 });

yolov8Cls.Predict(new List<Mat> { image1, image2, image3 });

yolov8Cls.Predict(new List<Mat> { image1, image2, image3, image4 });

yolov8Cls.Predict(new List<Mat> { image1, image2, image3, image4, image5 });

4.3 项目演示

配置好项目并编写好代码后,运行该项目,项目输出如下所示:

shell 复制代码
[ INFO ] Input image data processing time: 5.5277 ms.
[ INFO ] Model inference time: 1.3685 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Inference result processing time: 3.0823 ms.

[ INFO ] Input image data processing time: 2.7356 ms.
[ INFO ] Model inference time: 1.4435 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Classification Top 2 result :
[ INFO ] index: 14      score: 0.99853516
[ INFO ] index: 88      score: 0.0006980896
[ INFO ] Inference result processing time: 1.5137 ms.

[ INFO ] Input image data processing time: 3.7277 ms.
[ INFO ] Model inference time: 1.5285 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Classification Top 2 result :
[ INFO ] index: 14      score: 0.99853516
[ INFO ] index: 88      score: 0.0006980896
[ INFO ] Classification Top 2 result :
[ INFO ] index: 294     score: 0.96533203
[ INFO ] index: 269     score: 0.0124435425
[ INFO ] Inference result processing time: 2.7328 ms.

[ INFO ] Input image data processing time: 4.063 ms.
[ INFO ] Model inference time: 1.6947 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Classification Top 2 result :
[ INFO ] index: 14      score: 0.99853516
[ INFO ] index: 88      score: 0.0006980896
[ INFO ] Classification Top 2 result :
[ INFO ] index: 294     score: 0.96533203
[ INFO ] index: 269     score: 0.0124435425
[ INFO ] Classification Top 2 result :
[ INFO ] index: 127     score: 0.9008789
[ INFO ] index: 128     score: 0.07745361
[ INFO ] Inference result processing time: 3.5664 ms.

通过上面输出可以看出,不同Bath模型推理时间在1.3685~1.6947ms,大大提升了模型的推理速度。

5. 总结

在本项目中,我们扩展了TensorRT C# API 接口,使其支持动态输入模型。并结合分类模型部署流程向大家展示了TensorRT C# API 的使用方式,方便大家快速上手使用。

为了方便各位开发者使用,此处开发了配套的演示项目,主要是基于Yolov8开发的目标检测、目标分割、人体关键点识别、图像分类以及旋转目标识别,并且支持动态输入模型,用户可以同时推理任意张图像。

同时对本项目开发的案例进行了时间测试,以下时间只是程序运行一次的时间,测试环境为:

  • CPU:i7-165G7

  • CUDA型号:12.2

  • Cudnn:8.9.3

  • TensorRT:8.6.1.6

Model Batch 数据预处理 (ms) 模型推理 (ms) 结果后处理 (ms)
Yolov8s-Det 1 16.6 4.6 13.1
4 38.0 12.4 32.4
8 70.5 23.0 80.1
Yolov8s-Obb 1 28.7 8.9 17.7
4 81.7 25.9 67.4
8 148.4 44.6 153.0
Yolov8s-Seg 1 15.4 5.4 67.4
4 37.3 15.5 220.6
8 78.7 26.9 433.6
Yolov8s-Pose 1 15.1 5.2 8.7
4 39.2 13.2 14.3
8 67.8 23.1 27.7
Yolov8s-Cls 1 9.9 1.3 1.9
4 14.7 1.5 2.3
8 22.6 2.0 2.9

最后如果各位开发者在使用中有任何问题,欢迎大家与我联系。

相关推荐
向宇it5 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo5 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
Heaphaestus,RC6 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
baivfhpwxf20236 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾7 小时前
Scala全文单词统计
开发语言·c#·scala
ZwaterZ8 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
ZwaterZ10 小时前
el-table-column自动生成序号&&在序号前插入图标
前端·javascript·c#·vue
SRC_BLUE_1713 小时前
SQLI LABS | Less-55 GET-Challenge-Union-14 Queries Allowed-Variation 2
oracle·c#·less
yngsqq14 小时前
037集——JoinEntities连接多段线polyline和圆弧arc(CAD—C#二次开发入门)
开发语言·c#·swift
Zԅ(¯ㅂ¯ԅ)14 小时前
C#桌面应用制作计算器进阶版01
开发语言·c#