Yolov8简介
YOLOv8是Ultralytics公司推出的基于对象检测模型的YOLO最新系列,它能够提供截至目前最先进的对象检测性能。
借助于以前的YOLO模型版本支持技术,YOLOv8模型运行得更快、更准确,同时为执行任务的训练模型提供了统一的框架,这包括:
目标检测
实例分割
图像分类
YOLOv8也非常高效和灵活,它可以支持多种导出格式,而且该模型可以在CPU和GPU上运行。
使用Yolov8.Net
从GitHub上Clone Yolov8.Net。项目结构如下:

配置训练环境
Yolov8支持CPU和GPU进行推理。首先需要安装CUDA Toolkit和cuDNN模块,具体安装方法见教程,按照教程安装即可。CUDA与cuDNN安装教程(超详细)。
测试cuDNN是否正确配置
打开CUDA安装目录:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\extras\demo_suite
右键此处打开PowerShell
执行bandwidthTest.exe,结尾出现PASS

执行deviceQuery.exe,结尾出现PASS

完成单元测试

使用异常
[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。
使用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);
}
}
}
}
}