通过.Net平台使用Yolov8

YOLOv8是Ultralytics公司发布的最新对象检测模型,提供先进的检测性能并支持目标检测、实例分割和图像分类。文章讨论了如何配置训练环境,包括安装CUDA和CUDNN,以及测试其正确性。遇到的常见问题包括LoadLibrary失败,通常由于cuDNN未正确配置。此外,文章指出首次使用GPU推理时会因模型加载和参数导入导致较长延迟,但后续推理速度会显著提高。建议在实际应用中预加载模型以优化效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Yolov8简介

YOLOv8是Ultralytics公司推出的基于对象检测模型的YOLO最新系列,它能够提供截至目前最先进的对象检测性能。

借助于以前的YOLO模型版本支持技术,YOLOv8模型运行得更快、更准确,同时为执行任务的训练模型提供了统一的框架,这包括:

  • 目标检测

  • 实例分割

  • 图像分类

YOLOv8也非常高效和灵活,它可以支持多种导出格式,而且该模型可以在CPU和GPU上运行。

使用Yolov8.Net

从GitHub上Clone Yolov8.Net。项目结构如下:

配置训练环境

Yolov8支持CPU和GPU进行推理。首先需要安装CUDA Toolkit和cuDNN模块,具体安装方法见教程,按照教程安装即可。CUDA与cuDNN安装教程(超详细)

测试cuDNN是否正确配置

  1. 打开CUDA安装目录:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\extras\demo_suite

  1. 右键此处打开PowerShell

  1. 执行bandwidthTest.exe,结尾出现PASS

  1. 执行deviceQuery.exe,结尾出现PASS

完成单元测试

使用异常

  1. [ErrorCode:RuntimeException] FAIL : LoadLibrary failed with error 126

这个异常很常见,在Yolov5Net、Yolov7Net项目中issue中都能找到这个异常。主要是在使用GPU推理,即参数useGPU = True时导致异常。

异常详情:

"H:\Yolov8.Net\test\Yolov8net.test\bin\Debug\net6.0\runtimes\win-x64\native\onnxruntime_providers_cuda.dll"
 Microsoft.ML.OnnxRuntime.OnnxRuntimeException : [ErrorCode:RuntimeException] FAIL : LoadLibrary failed with error 126 "" when trying to load "\runtimes\win-x64\native\onnxruntime_providers_cuda.dll"

异常原因:

cuDNN模块未配置。安装【配置训练环境】中的教程依次安装CUDN和配置cuDNN。

  1. 使用GPU推理比CPU耗时更长

这个问题我测试的时候也遇到了,如上图中,GPU推理耗时6.7s,远远大于CPU耗时900ms。于是,我把GPU推理单独拿出来做个正常的Demo。

以下是测试结果:

可以看出:加载模型耗时接近3s,

因为GPU与CPU的运算机制不同,第一次使用GPU推理时,会将参数导入GPU网格,所以耗时也比较久,但是之后的测试效率就猛的提高了,比CPU耗时要短了。

这个问题我在【Yolov8.Net】的issue也提及了:Why does it take longer to predict using the GPU than using the CPU? · Issue #13 · sstainba/Yolov8.Net (github.com)

同样有人问我是否解决。这个问题只要是在测试模式,每次都重新加载模型运算,效率始终提不上来的。

所以,运用在实际项目中时,可以在程序初始化时加载模型,然后自动先运行一次推理,之后的推理效率就高了。

这种操作方式同样适用其他模型的推理。

这里贴一下测试程序:

using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using Yolov8Net;

namespace TestCUDACoco
{
    internal class Program
    {
        static string path;
        static Stopwatch stopwatch = new Stopwatch();
        static void Main(string[] args)
        {
            stopwatch.Restart();
            stopwatch.Start();
            Console.WriteLine("Hello, World!");
            using var yolo = YoloV8Predictor.Create("./assets/yolov8m.onnx", null, true);
            //Assert.NotNull(yolo);
            stopwatch.Stop();
            Console.WriteLine($"Load Model Elapsed Time:{stopwatch.ElapsedMilliseconds.ToString()}");
            int ct = 1;
            while (true)
            {
                Console.WriteLine("Input the image path :");
                path = Console.ReadLine();
                if (path == "q")
                {
                    break;
                }
                else if(path =="")
                {
                    continue;
                }
                stopwatch.Restart();
                stopwatch.Start();
                //using var image = Image.FromFile("Assets/cars/TY_V3_CarInCP_211106234704.jpg");
                using var image = Image.FromFile(path);
                var predictions = yolo.Predict(image);

                //Assert.NotNull(predictions);

                DrawBoxes(yolo.ModelInputHeight, yolo.ModelInputWidth, image, predictions);

                image.Save("resultCuda.jpg");
                stopwatch.Stop();
                Console.WriteLine($" NO.{ct } Predict Elapsed Time :{stopwatch.ElapsedMilliseconds.ToString()}");
                ct++;
            }
            
        }
        private static void DrawBoxes(int modelInputHeight, int modelInputWidth, Image image, Prediction[] predictions)
        {
            foreach (var pred in predictions)
            {
                var originalImageHeight = image.Height;
                var originalImageWidth = image.Width;

                var x = Math.Max(pred.Rectangle.X, 0);
                var y = Math.Max(pred.Rectangle.Y, 0);
                var width = Math.Min(originalImageWidth - x, pred.Rectangle.Width);
                var height = Math.Min(originalImageHeight - y, pred.Rectangle.Height);

                //Note that the output is already scaled to the original image height and width.

                // Bounding Box Text
                string text = $"{pred.Label.Name} [{pred.Score}]";

                using (Graphics graphics = Graphics.FromImage(image))
                {
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.SmoothingMode = SmoothingMode.HighQuality;
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                    // Define Text Options
                    Font drawFont = new Font("consolas", 11, FontStyle.Regular);
                    SizeF size = graphics.MeasureString(text, drawFont);
                    SolidBrush fontBrush = new SolidBrush(Color.Black);
                    Point atPoint = new Point((int)x, (int)y - (int)size.Height - 1);

                    // Define BoundingBox options
                    Pen pen = new Pen(Color.Yellow, 2.0f);
                    SolidBrush colorBrush = new SolidBrush(Color.Yellow);

                    // Draw text on image 
                    graphics.FillRectangle(colorBrush, (int)x, (int)(y - size.Height - 1), (int)size.Width, (int)size.Height);
                    graphics.DrawString(text, drawFont, fontBrush, atPoint);

                    // Draw bounding box on image
                    graphics.DrawRectangle(pen, x, y, width, height);
                }
            }
        }
    }
}
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值