前言

前段时间玩了把yolo,结果卡在用winform调用模型实识别的过程.从网络上找了很长一段时间代码,结果总不尽人意.今天隔离结束,回到工位,继续撸代码.

环境

vs2019,Net5,ML.OnnxRuntime,SixLabors.

准备

nuget下载如下包,

下载onnx权重文件

models/FasterRCNN-10.onnx at main · onnx/models · GitHub

代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.ML.OnnxRuntime.Tensors;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.Fonts;
//using SixLabors.Fonts;
//using System.Drawing;

namespace Microsoft.ML.OnnxRuntime.FasterRcnnSample
{
    class Program
    {
        public static void Main(string[] args)
        {


            // Read paths
            string modelFilePath = @"D:\Test\2022\FasterRCNN-10.onnx";
            //string modelFilePath = @"D:\Test\2022\best.onnx";
            // string imageFilePath = @"D:\Test\2022\A.jpg";
            string imageFilePath = @"D:\Test\2022\B.png";
            string outImageFilePath = "outputs.jpg";
            //System.IO.Directory.CreateDirectory(outImageFilePath);


            // Read image
            using Image<Rgb24> image = SixLabors.ImageSharp.Image.Load<Rgb24>(imageFilePath);

            // Resize image
            float ratio = 800f / Math.Min(image.Width, image.Height);
            image.Mutate(x => x.Resize((int)(ratio * image.Width), (int)(ratio * image.Height)));

            // Preprocess image
            var paddedHeight = (int)(Math.Ceiling(image.Height / 32f) * 32f);
            var paddedWidth = (int)(Math.Ceiling(image.Width / 32f) * 32f);
            Tensor<float> input = new DenseTensor<float>(new[] { 3, paddedHeight, paddedWidth });
            var mean = new[] { 102.9801f, 115.9465f, 122.7717f };
            for (int y = paddedHeight - image.Height; y < image.Height; y++)
            {
                image.ProcessPixelRows(im =>
                {
                    var pixelSpan = im.GetRowSpan(y);
                    for (int x = paddedWidth - image.Width; x < image.Width; x++)
                    {
                        input[0, y, x] = pixelSpan[x].B - mean[0];
                        input[1, y, x] = pixelSpan[x].G - mean[1];
                        input[2, y, x] = pixelSpan[x].R - mean[2];
                    }
                });

            }

            // Setup inputs and outputs
            var inputs = new List<NamedOnnxValue>
            {
                NamedOnnxValue.CreateFromTensor("image", input)
            };

            // Run inference
            using var session = new InferenceSession(modelFilePath);
            using IDisposableReadOnlyCollection<DisposableNamedOnnxValue> results = session.Run(inputs);

            // Postprocess to get predictions
            var resultsArray = results.ToArray();
            float[] boxes = resultsArray[0].AsEnumerable<float>().ToArray();
            long[] labels = resultsArray[1].AsEnumerable<long>().ToArray();
            float[] confidences = resultsArray[2].AsEnumerable<float>().ToArray();



            var predictions = new List<Prediction>();
            var minConfidence = 0.7f;
            for (int i = 0; i < boxes.Length - 4; i += 4)
            {
                var index = i / 4;
                if (confidences[index] >= minConfidence)
                {
                    predictions.Add(new Prediction
                    {
                        Box = new Box(boxes[i], boxes[i + 1], boxes[i + 2], boxes[i + 3]),
                        Label = LabelMap.Labels[labels[index]],
                        Confidence = confidences[index]
                    });
                }
            }

            // Put boxes, labels and confidence on image and save for viewing
            using var outputImage = File.OpenWrite(outImageFilePath);
           Font font = SystemFonts.CreateFont("Arial",16);
            foreach (var p in predictions)
            {
                image.Mutate(x =>
                {
                    x.DrawLines(Color.Red, 2f, new PointF[] {

                        new SixLabors.ImageSharp.PointF(p.Box.Xmin, p.Box.Ymin),
                        new SixLabors.ImageSharp.PointF(p.Box.Xmax, p.Box.Ymin),

                        new PointF(p.Box.Xmax, p.Box.Ymin),
                        new PointF(p.Box.Xmax, p.Box.Ymax),

                        new PointF(p.Box.Xmax, p.Box.Ymax),
                        new PointF(p.Box.Xmin, p.Box.Ymax),

                        new PointF(p.Box.Xmin, p.Box.Ymax),
                        new PointF(p.Box.Xmin, p.Box.Ymin)
                    });
                    x.DrawText($"{p.Label}, {p.Confidence:0.00}", font, Color.White, new PointF(p.Box.Xmin, p.Box.Ymin));
                });
            }
            image.SaveAsJpeg(outputImage);
        }
    }
    public class Prediction
    {
        public Box Box { set; get; }
        public string Label { set; get; }
        public float Confidence { set; get; }
    }
    public class Box
    {
        public Box(float xMin,float yMin,float xMax,float yMax)
        {
            Xmin = xMin;
            Ymin = yMin;
            Xmax = xMax;
            Ymax = yMax;
        }
        public float Xmin { set; get; }
        public float Xmax { set; get; }
        public float Ymin { set; get; }
        public float Ymax { set; get; }
    }

    public static class LabelMap
    {
        static LabelMap()
        {
            Labels = new string[]
            {
             "",
            "person",
            "bicycle",
            "car",
            "motorcycle",
            "airplane",
            "bus",
            "train",
            "truck",
            "boat",
            "traffic light",
            "fire hydrant",
            "stop sign",
            "parking meter",
            "bench",
            "bird",
            "cat",
            "dog",
            "horse",
            "sheep",
            "cow",
            "elephant",
            "bear",
            "zebra",
            "giraffe",
            "backpack",
            "umbrella",
            "handbag",
            "tie",
            "suitcase",
            "frisbee",
            "skis",
            "snowboard",
            "sports ball",
            "kite",
            "baseball bat",
            "baseball glove",
            "skateboard",
            "surfboard",
            "tennis racket",
            "bottle",
            "wine glass",
            "cup",
            "fork",
            "knife",
            "spoon",
            "bowl",
            "banana",
            "apple",
            "sandwich",
            "orange",
            "broccoli",
            "carrot",
            "hot dog",
            "pizza",
            "donut",
            "cake",
            "chair",
            "couch",
            "potted plant",
            "bed",
            "dining table",
            "toilet",
            "tv",
            "laptop",
            "mouse",
            "remote",
            "keyboard",
            "cell phone",
            "microwave",
            "oven",
            "toaster",
            "sink",
            "refrigerator",
            "book",
            "clock",
            "vase",
            "scissors",
            "teddy bear",
            "hair drier",
            "toothbrush"
            };
        }

        public static string[] Labels { set; get; }
    }
}

说明

 1.NamedOnnxValue.CreateFromTensor("image", input),这里面的"image"可以从WinMLDashboard软件中看到.

2.image.GetPixelRowSpan() 方法已经被 image.ProcessPixelRows()方法取代.这个东西找了半天.

3.Prediction,Box,LabelMap,是自己补全的.没找到网上的源代码.

效果

 随便从网上找的图片.如有侵权,请联系本人.

引用

Mr.Q老师的博客

(20条消息) c# 部署onnx定位模型_Mr.Q的博客-CSDN博客_onnx模型部署

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐