.NetFramework平台,C# Onnx Yolov8 Detect ,怎么推理啊,尝试了几次好像结果都不对
```
.NetFramework平台,C# Onnx Yolov8 Detect ,怎么推理啊,尝试了几次好像结果都不对
```
上午好☀️☀️☀️️
本答案参考通义千问
在 .NET Framework 平台上使用 C# 进行 ONNX YOLOv8 的目标检测(Detect)推理,确实是一个常见的任务。如果你尝试了几次但结果不对,可能是以下几个原因导致的:
模型加载错误
.onnx 文件)输入预处理错误
640x640)输出后处理错误
环境依赖问题
onnxruntime 或 onnxruntime.shared 等依赖库确保你安装了以下 NuGet 包:
Install-Package Microsoft.ML.OnnxRuntime
Install-Package Microsoft.ML.OnnxRuntime.Shared
注意: 如果你使用的是 .NET Framework 4.7.2+,这些包应该可以正常工作。
using System;
using System.Drawing;
using System.IO;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
class Program
{
static void Main(string[] args)
{
string modelPath = @"path\to\yolov8s.onnx"; // 替换为你的模型路径
string imagePath = @"path\to\test.jpg"; // 替换为你的图片路径
using (var session = new InferenceSession(modelPath))
{
var image = new Bitmap(imagePath);
var inputTensor = PreprocessImage(image);
var inputs = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor("images", inputTensor)
};
using (var results = session.Run(inputs))
{
var output = results[0].AsTensor<float>();
var detections = PostProcess(output, image.Width, image.Height);
foreach (var detection in detections)
{
Console.WriteLine($"Class: {detection.Class}, Confidence: {detection.Confidence}, BBox: {detection.BoundingBox}");
}
}
}
}
static DenseTensor<float> PreprocessImage(Bitmap image)
{
int width = 640;
int height = 640;
// Resize to 640x640
var resized = new Bitmap(image, new Size(width, height));
// Convert to float and normalize [0,1]
var tensor = new DenseTensor<float>(new[] { 1, 3, height, width });
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var pixel = resized.GetPixel(x, y);
tensor[0, 0, y, x] = pixel.R / 255.0f;
tensor[0, 1, y, x] = pixel.G / 255.0f;
tensor[0, 2, y, x] = pixel.B / 255.0f;
}
}
return tensor;
}
static List<Detection> PostProcess(DenseTensor<float> output, int originalWidth, int originalHeight)
{
var detections = new List<Detection>();
// 假设输出是 [1, 84, 8400],其中 84 = 4 + 80 (坐标 + 类别)
int numClasses = 80; // YOLOv8 默认有 80 个类别
int numBoxes = 8400;
for (int i = 0; i < numBoxes; i++)
{
float confidence = output[0, 4 + 0, i]; // 第一个类别的置信度
if (confidence < 0.25) continue;
float x = output[0, 0, i];
float y = output[0, 1, i];
float w = output[0, 2, i];
float h = output[0, 3, i];
float left = (x - w / 2) * originalWidth;
float top = (y - h / 2) * originalHeight;
float right = (x + w / 2) * originalWidth;
float bottom = (y + h / 2) * originalHeight;
for (int c = 0; c < numClasses; c++)
{
float classScore = output[0, 4 + c + 1, i];
if (classScore > confidence)
{
confidence = classScore;
// 可以在这里添加 NMS 处理
}
}
detections.Add(new Detection
{
Class = "Class" + (int)(confidence * 100),
Confidence = confidence,
BoundingBox = new RectangleF(left, top, right - left, bottom - top)
});
}
return detections;
}
class Detection
{
public string Class { get; set; }
public float Confidence { get; set; }
public RectangleF BoundingBox { get; set; }
}
}
输入图像必须为 640x640
YOLOv8 的输入尺寸必须是 640x640,否则模型会输出错误结果。
归一化方式必须一致
将像素值除以 255,且 通道顺序为 BGR(如果模型训练时用的是 BGR)。
输出格式要解析正确
YOLOv8 的输出通常是
[batch_size, 4 + num_classes, num_boxes],你需要提取每个 box 的坐标和类别。
NMS(非极大值抑制)非常重要
如果没有 NMS,同一个物体可能会被多次检测,导致结果混乱。
打印模型输入/输出维度
var inputs = session.InputMetadata;
var outputs = session.OutputMetadata;
foreach (var item in inputs)
{
Console.WriteLine($"Input: {item.Key} -> {item.Value.Dimensions}");
}
foreach (var item in outputs)
{
Console.WriteLine($"Output: {item.Key} -> {item.Value.Dimensions}");
}
查看模型是否支持 GPU 推理
var options = new SessionOptions();
options.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_ALL;
options.AppendExecutionProvider_CUDA(); // 如果可用
var session = new InferenceSession(modelPath, options);
| 工具 | 用途 | |------|------| | ONNX Model Zoo | 获取官方模型 | | YOLOv8 GitHub | 查看模型结构 | | ONNX Runtime C# 文档 | API参考 |
在 .NET Framework 中使用 C# + ONNX YOLOv8 进行目标检测的关键在于:
如果你能按照上述步骤实现,并检查每一步的输出是否符合预期,就能逐步排查出问题所在。
如有具体错误信息或模型结构问题,欢迎继续提问!