最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中使用YOLO的常用方式的詳細指南

 更新時間:2025年05月15日 09:18:12   作者:LeonDL168  
在C#中使用YOLO(You Only Look Once)目標檢測算法,通常有幾種不同的實現方式,例如OpenCV,ONNX Runtime等,下面我們來看看具體的操作方法吧

在C#中使用YOLO(You Only Look Once)目標檢測算法,通常有幾種不同的實現方式,包括使用OpenCV、ONNX Runtime或ML.NET等框架。下面為你介紹兩種常見的實現方法:

方法一:使用ONNX Runtime部署YOLOv5模型

這種方法的優(yōu)勢在于實現簡單,且性能優(yōu)化較好。

具體步驟

1.準備YOLOv5模型

首先,從YOLOv5官方倉庫(https://github.com/ultralytics/yolov5 )下載預訓練模型。

然后,將PyTorch模型轉換為ONNX格式:

python export.py --weights yolov5s.pt --include onnx

2.創(chuàng)建C#項目并安裝NuGet包

新建一個.NET Core控制臺應用程序。

通過NuGet包管理器安裝以下組件:

  • Microsoft.ML.OnnxRuntime
  • System.Drawing.Common(用于圖像處理)

實現代碼

下面是一個完整的示例代碼

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;

namespace YoloV5OnnxRuntime
{
    class Program
    {
        // 檢測類別名稱
        private static readonly string[] classNames = new[] {
            "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"
        };

        static void Main(string[] args)
        {
            // 模型路徑和輸入圖像路徑
            string modelPath = "yolov5s.onnx";
            string imagePath = "test.jpg";
            
            // 加載模型
            using var session = new InferenceSession(modelPath);
            
            // 加載并預處理圖像
            var (inputTensor, originalWidth, originalHeight) = LoadImage(imagePath);
            
            // 準備輸入參數
            var inputs = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("images", inputTensor) };
            
            // 運行模型推理
            using var results = session.Run(inputs);
            
            // 處理輸出結果
            var outputTensor = results.First().AsTensor<float>();
            var predictions = ProcessOutput(outputTensor, originalWidth, originalHeight);
            
            // 繪制檢測結果
            DrawPredictions(imagePath, predictions, "output.jpg");
            
            Console.WriteLine("檢測完成,結果已保存至 output.jpg");
        }

        // 加載并預處理圖像
        private static (DenseTensor<float> tensor, int width, int height) LoadImage(string imagePath)
        {
            using var image = Image.FromFile(imagePath);
            int originalWidth = image.Width;
            int originalHeight = image.Height;
            
            // 調整圖像大小為模型輸入尺寸(通常為640x640)
            var resizedImage = ResizeImage(image, 640, 640);
            
            // 圖像轉張量
            var tensor = new DenseTensor<float>(new[] { 1, 3, 640, 640 });
            var mean = new[] { 0.0f, 0.0f, 0.0f }; // 均值
            var std = new[] { 1.0f, 1.0f, 1.0f };  // 標準差
            
            using (var bitmap = new Bitmap(resizedImage))
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    for (int x = 0; x < bitmap.Width; x++)
                    {
                        var pixel = bitmap.GetPixel(x, y);
                        
                        // 注意:圖像通道順序為BGR(OpenCV默認),而模型可能需要RGB
                        tensor[0, 0, y, x] = (pixel.R / 255.0f - mean[0]) / std[0];
                        tensor[0, 1, y, x] = (pixel.G / 255.0f - mean[1]) / std[1];
                        tensor[0, 2, y, x] = (pixel.B / 255.0f - mean[2]) / std[2];
                    }
                }
            }
            
            return (tensor, originalWidth, originalHeight);
        }

        // 調整圖像大小
        private static Image ResizeImage(Image image, int width, int height)
        {
            var destRect = new Rectangle(0, 0, width, height);
            var destImage = new Bitmap(width, height);
            
            destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
            
            using (var graphics = Graphics.FromImage(destImage))
            {
                graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                
                using (var wrapMode = new System.Drawing.Imaging.ImageAttributes())
                {
                    wrapMode.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }
            
            return destImage;
        }

        // 處理模型輸出
        private static List<Prediction> ProcessOutput(Tensor<float> output, int originalWidth, int originalHeight)
        {
            const float confidenceThreshold = 0.5f;
            const float nmsThreshold = 0.4f;
            
            var predictions = new List<Prediction>();
            
            // 解析模型輸出
            for (int i = 0; i < output.Length / 85; i++)
            {
                float confidence = output[0, i, 4];
                
                if (confidence >= confidenceThreshold)
                {
                    // 找到概率最高的類別
                    int classId = 0;
                    float maxClassProbs = 0;
                    
                    for (int c = 0; c < 80; c++)
                    {
                        float classProbs = output[0, i, 5 + c];
                        if (classProbs > maxClassProbs)
                        {
                            maxClassProbs = classProbs;
                            classId = c;
                        }
                    }
                    
                    float score = confidence * maxClassProbs;
                    
                    if (score >= confidenceThreshold)
                    {
                        // 獲取邊界框坐標
                        float cx = output[0, i, 0];
                        float cy = output[0, i, 1];
                        float w = output[0, i, 2];
                        float h = output[0, i, 3];
                        
                        // 轉換為左上角和右下角坐標
                        float x1 = (cx - w / 2) / 640.0f * originalWidth;
                        float y1 = (cy - h / 2) / 640.0f * originalHeight;
                        float x2 = (cx + w / 2) / 640.0f * originalWidth;
                        float y2 = (cy + h / 2) / 640.0f * originalHeight;
                        
                        predictions.Add(new Prediction
                        {
                            ClassId = classId,
                            Score = score,
                            BBox = new RectangleF(x1, y1, x2 - x1, y2 - y1)
                        });
                    }
                }
            }
            
            // 非極大值抑制
            return NonMaxSuppression(predictions, nmsThreshold);
        }

        // 非極大值抑制
        private static List<Prediction> NonMaxSuppression(List<Prediction> predictions, float threshold)
        {
            var result = new List<Prediction>();
            
            // 按置信度降序排序
            predictions = predictions.OrderByDescending(p => p.Score).ToList();
            
            while (predictions.Count > 0)
            {
                var best = predictions[0];
                result.Add(best);
                predictions.RemoveAt(0);
                
                // 移除重疊度高的邊界框
                predictions = predictions.Where(p => IoU(best.BBox, p.BBox) < threshold).ToList();
            }
            
            return result;
        }

        // 計算交并比
        private static float IoU(RectangleF a, RectangleF b)
        {
            float areaA = a.Width * a.Height;
            if (areaA <= 0) return 0;
            
            float areaB = b.Width * b.Height;
            if (areaB <= 0) return 0;
            
            float minX = Math.Max(a.Left, b.Left);
            float minY = Math.Max(a.Top, b.Top);
            float maxX = Math.Min(a.Right, b.Right);
            float maxY = Math.Min(a.Bottom, b.Bottom);
            
            float intersectionWidth = maxX - minX;
            float intersectionHeight = maxY - minY;
            
            if (intersectionWidth <= 0 || intersectionHeight <= 0)
                return 0;
                
            float intersectionArea = intersectionWidth * intersectionHeight;
            return intersectionArea / (areaA + areaB - intersectionArea);
        }

        // 繪制預測結果
        private static void DrawPredictions(string inputImagePath, List<Prediction> predictions, string outputImagePath)
        {
            using var image = Image.FromFile(inputImagePath);
            using var graphics = Graphics.FromImage(image);
            
            // 設置繪圖質量
            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            
            // 繪制邊界框和標簽
            foreach (var prediction in predictions)
            {
                var bbox = prediction.BBox;
                var label = $"{classNames[prediction.ClassId]}: {prediction.Score:F2}";
                
                // 繪制邊界框
                using var pen = new Pen(Color.FromArgb(255, 255, 0, 0), 2);
                graphics.DrawRectangle(pen, bbox.X, bbox.Y, bbox.Width, bbox.Height);
                
                // 繪制標簽背景
                using var font = new Font("Arial", 10, FontStyle.Bold);
                using var brush = new SolidBrush(Color.FromArgb(255, 255, 0, 0));
                using var textBrush = new SolidBrush(Color.White);
                
                var textSize = graphics.MeasureString(label, font);
                var textBackground = new RectangleF(bbox.X, bbox.Y - textSize.Height, textSize.Width, textSize.Height);
                
                graphics.FillRectangle(brush, textBackground);
                graphics.DrawString(label, font, textBrush, bbox.X, bbox.Y - textSize.Height);
            }
            
            // 保存結果圖像
            image.Save(outputImagePath, ImageFormat.Jpeg);
        }
    }

    // 預測結果類
    public class Prediction
    {
        public int ClassId { get; set; }
        public float Score { get; set; }
        public RectangleF BBox { get; set; }
    }
}

方法二:使用ML.NET部署YOLOv5模型

ML.NET是微軟的跨平臺機器學習框架,也可用于部署YOLO模型。

具體步驟

1.準備工作與方法一相同

下載并轉換YOLOv5模型。

創(chuàng)建C#項目并安裝必要的NuGet包:

  • Microsoft.ML
  • Microsoft.ML.OnnxTransformer

實現代碼

下面是使用ML.NET的示例代碼:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.OnnxTransformer;
using Microsoft.ML.Trainers;

namespace YoloV5MLNet
{
    class Program
    {
        // 檢測類別名稱(同上)
        private static readonly string[] classNames = new[] { ... }; // 同上,省略
        
        static void Main(string[] args)
        {
            string modelPath = "yolov5s.onnx";
            string imagePath = "test.jpg";
            
            // 創(chuàng)建MLContext
            var mlContext = new MLContext();
            
            // 定義模型輸入輸出架構
            var data = new List<ImageInputData> { new ImageInputData { ImagePath = imagePath } };
            var dataView = mlContext.Data.LoadFromEnumerable(data);
            
            // 定義數據轉換管道
            var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "image", imageFolder: "", inputColumnName: nameof(ImageInputData.ImagePath))
                .Append(mlContext.Transforms.ResizeImages(outputColumnName: "image", imageWidth: 640, imageHeight: 640, inputColumnName: "image"))
                .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "images", inputColumnName: "image", interleavePixelColors: true, offsetImage: 0))
                .Append(mlContext.Transforms.ApplyOnnxModel(
                    shapeDictionary: new Dictionary<string, int[]>()
                    {
                        { "images", new[] { 1, 3, 640, 640 } },
                        { "output", new[] { 1, 25200, 85 } }
                    },
                    inputColumnNames: new[] { "images" },
                    outputColumnNames: new[] { "output" },
                    modelFile: modelPath));
            
            // 訓練管道(這里只是為了創(chuàng)建預測引擎)
            var model = pipeline.Fit(dataView);
            
            // 創(chuàng)建預測引擎
            var predictor = mlContext.Model.CreatePredictionEngine<ImageInputData, ImagePrediction>(model);
            
            // 進行預測
            var prediction = predictor.Predict(new ImageInputData { ImagePath = imagePath });
            
            // 處理輸出結果
            var originalImage = Image.FromFile(imagePath);
            var predictions = ProcessOutput(prediction.Output, originalImage.Width, originalImage.Height);
            
            // 繪制檢測結果
            DrawPredictions(imagePath, predictions, "output.jpg");
            
            Console.WriteLine("檢測完成,結果已保存至 output.jpg");
        }

        // 圖像處理和結果解析方法(與ONNX Runtime版本相同)
        private static List<Prediction> ProcessOutput(float[] output, int originalWidth, int originalHeight)
        {
            // 與ONNX Runtime版本中的ProcessOutput方法相同
            // ...
        }

        // 非極大值抑制和IoU計算方法(同上)
        private static List<Prediction> NonMaxSuppression(List<Prediction> predictions, float threshold)
        {
            // ...
        }
        
        private static float IoU(RectangleF a, RectangleF b)
        {
            // ...
        }

        // 繪制預測結果(同上)
        private static void DrawPredictions(string inputImagePath, List<Prediction> predictions, string outputImagePath)
        {
            // ...
        }
    }

    // 數據模型類
    public class ImageInputData
    {
        [LoadColumn(0)]
        public string ImagePath { get; set; }
    }

    public class ImagePrediction
    {
        [ColumnName("output")]
        public float[] Output { get; set; }
    }

    // 預測結果類(同上)
    public class Prediction
    {
        public int ClassId { get; set; }
        public float Score { get; set; }
        public RectangleF BBox { get; set; }
    }
}

性能優(yōu)化建議

使用GPU加速:若要提升檢測速度,可安裝CUDA版本的ONNX Runtime,這樣就能利用GPU進行推理。

模型量化:可以將FP32模型轉換為INT8量化模型,以此減小模型體積并提高推理速度。

批量處理:如果需要處理大量圖像,可以考慮使用批量輸入來提高吞吐量。

異步推理:對于實時應用場景,建議使用異步API來避免阻塞主線程。

通過上述方法,你可以在C#環(huán)境中實現YOLO目標檢測功能。ONNX Runtime方法更為直接,而ML.NET方法則能更好地與微軟生態(tài)系統(tǒng)集成。你可以根據自己的具體需求選擇合適的實現方式。

到此這篇關于C#中使用YOLO的常用方式的詳細指南的文章就介紹到這了,更多相關C#使用YOLO內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C#中CompareTo的用法小結

    C#中CompareTo的用法小結

    CompareTo方法通常用于比較當前對象與另一個對象的順序,本文主要介紹了C#中CompareTo的用法小結,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • C#利用System.Uri轉URL為絕對地址的方法

    C#利用System.Uri轉URL為絕對地址的方法

    這篇文章主要介紹了C#利用System.Uri轉URL為絕對地址的方法,涉及C#操作URL的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-02-02
  • C#實現啟動,關閉與查找進程的方法

    C#實現啟動,關閉與查找進程的方法

    這篇文章主要介紹了C#實現啟動,關閉與查找進程的方法,通過簡單實例形式分析了C#針對進程的啟動,關閉與查找的相關實現技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • C#?基礎數據類型之字符串類型詳解

    C#?基礎數據類型之字符串類型詳解

    C#字符串作為引用類型卻常被當作值類型使用,探討其不可變性、字符串駐留及常用操作,本文給大家介紹C#?基礎數據類型之字符串類型,感興趣的朋友一起看看吧
    2026-05-05
  • C#實現綁定Combobox的方法

    C#實現綁定Combobox的方法

    這篇文章主要介紹了C#實現綁定Combobox的方法,涉及Combobox參數設置的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • C#優(yōu)化if...else代碼的方案總結

    C#優(yōu)化if...else代碼的方案總結

    在編寫代碼實現業(yè)務需求過程中,會使用到大量的if...else 判斷語句,隨業(yè)務復雜程度不同,導致判斷語句出現多層嵌套、多分支等情況,導致代碼可讀性變差、增加維護難度,本文介紹了C# 如何優(yōu)化 if...else 讓代碼優(yōu)雅起來,需要的朋友可以參考下
    2024-06-06
  • C# 讀取指定路徑配置文件的方法

    C# 讀取指定路徑配置文件的方法

    為了實現多個C#程序共用一個config文件,需要程序讀取指定路徑的config文件。代碼如下:
    2013-03-03
  • 基于Silverlight打印的使用詳解,是否為微軟的Bug問題

    基于Silverlight打印的使用詳解,是否為微軟的Bug問題

    本篇文章對Silverlight打印的使用進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C#使用正則表達式實現常見的格式驗證

    C#使用正則表達式實現常見的格式驗證

    這篇文章主要為大家詳細介紹了C#如何使用正則表達式實現常見的格式驗證,例如:電話號碼、密碼、郵編等,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-01-01
  • C#中使用DevExpress中的ChartControl實現極坐標圖的案例詳解

    C#中使用DevExpress中的ChartControl實現極坐標圖的案例詳解

    這篇文章主要介紹了在C#中使用DevExpress中的ChartControl實現極坐標圖,本案例是使用的是DevExpress 18.1.3版本,之前在14版本上也試過,但是有一個弊端就是實現極坐標圖的時候,第一個點和最后一個點總是自動多一條閉合線,會形成一個閉合的多邊形,因此升級了一下版
    2022-02-02

最新評論

托克托县| 于都县| 大兴区| 潼关县| 云和县| 宝应县| 神农架林区| 罗甸县| 西安市| 东兴市| 巴马| 满洲里市| 绥棱县| 门头沟区| 共和县| 张掖市| 卢湾区| 凤山市| 巴马| 汕尾市| 内黄县| 阿拉善左旗| 青海省| 儋州市| 建始县| 手游| 左权县| 郓城县| 湘西| 奉贤区| 鄂尔多斯市| 蓝山县| 天水市| 新蔡县| 南皮县| 陵水| 门源| 岐山县| 墨竹工卡县| 庆安县| 天镇县|