qq_27049053 2025-08-21 10:00 采纳率: 0%
浏览 22

.NetFramework平台,C# Onnx Yolov8

.NetFramework平台,C# Onnx Yolov8 Detect ,怎么推理啊,尝试了几次好像结果都不对

```

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-08-21 10:01
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    .NET Framework 平台上使用 C# 进行 ONNX YOLOv8 的目标检测(Detect)推理,确实是一个常见的任务。如果你尝试了几次但结果不对,可能是以下几个原因导致的:


    一、常见问题分析

    1. 模型加载错误

      • 模型路径不正确
      • 模型格式不支持(如不是 .onnx 文件)
      • ONNX运行时版本不兼容
    2. 输入预处理错误

      • 输入尺寸不符合模型要求(YOLOv8通常需要 640x640
      • 归一化方式错误(如未除以255或没有减去均值)
      • 图像通道顺序错误(BGR vs RGB)
    3. 输出后处理错误

      • 解析输出张量的方式不正确
      • NMS(非极大值抑制)参数设置不当
      • 类别映射错误或标签文件未加载
    4. 环境依赖问题

      • 缺少 onnxruntimeonnxruntime.shared 等依赖库
      • .NET Framework 版本与 ONNX 库不兼容

    二、解决步骤(详细流程)

    1. 安装必要的NuGet包

    确保你安装了以下 NuGet 包:

    Install-Package Microsoft.ML.OnnxRuntime
    Install-Package Microsoft.ML.OnnxRuntime.Shared
    

    注意: 如果你使用的是 .NET Framework 4.7.2+,这些包应该可以正常工作。


    2. 加载ONNX模型并进行推理

    示例代码(C#):

    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; }
        }
    }
    

    三、关键注意事项(重点!)

    1. 输入图像必须为 640x640

      YOLOv8 的输入尺寸必须是 640x640,否则模型会输出错误结果。

    2. 归一化方式必须一致

      将像素值除以 255,且 通道顺序为 BGR(如果模型训练时用的是 BGR)。

    3. 输出格式要解析正确

      YOLOv8 的输出通常是 [batch_size, 4 + num_classes, num_boxes],你需要提取每个 box 的坐标和类别。

    4. 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 进行目标检测的关键在于:

    1. 正确加载模型
    2. 正确预处理输入图像
    3. 正确解析模型输出
    4. 合理设置 NMS 参数

    如果你能按照上述步骤实现,并检查每一步的输出是否符合预期,就能逐步排查出问题所在。

    如有具体错误信息或模型结构问题,欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 创建了问题 8月21日