機器學習框架ML.NET學習筆記【8】目標檢測(採用YOLO2模型)

1、概述html

本篇文章介紹經過YOLO模型進行目標識別的應用,原始代碼來源於:https://github.com/dotnet/machinelearning-samplesgit

實現的功能是輸入一張圖片,對圖片中的目標進行識別,輸出結果在圖片中經過紅色框線標記出來。以下:github

 YOLO簡介數組

 YOLO(You Only Look Once)是一種最早進的實時目標檢測系統。官方網站:https://pjreddie.com/darknet/yolo/網絡

 本文采用的是TinyYolo2模型,能夠識別的目標類型包括:"aeroplane", "bicycle", "bird", "boat", "bottle","bus", "car", "cat", "chair", "cow","diningtable", "dog", "horse", "motorbike", "person","pottedplant", "sheep", "sofa", "train", "tvmonitor" 。 框架

ONNX簡介機器學習

ONNX 即Open Neural Network Exchange(開放神經網絡交換格式),是一個用於表示深度學習模型的通用標準,可以使模型在不一樣框架之間進行互相訪問,其規範及代碼主要由微軟,亞馬遜 ,Facebook 和 IBM 等公司共同制定與開發。有了ONNX標準,咱們就能夠在ML.NET代碼中使用經過其餘機器學習框架訓練並保存的模型。ide

 

2、代碼分析工具

 一、Main方法學習

        static void Main(string[] args)
        {
            TrainAndSave();
            LoadAndPredict();

            Console.WriteLine("Press any key to exit!");
            Console.ReadKey();
        }

 第一次運行時須要運行TrainAndSave方法,生成本地模型後,能夠直接運行生產代碼。

 

二、訓練並保存模型

     static readonly string tagsTsv = Path.Combine(trainImagesFolder,  "tags.tsv");       
     private static void TrainAndSave() { var mlContext = new MLContext(); var trainData = mlContext.Data.LoadFromTextFile<ImageNetData>(tagsTsv); var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "image", imageFolder: trainImagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)) .Append(mlContext.Transforms.ResizeImages(outputColumnName: "image", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "image")) .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "image")) .Append(mlContext.Transforms.ApplyOnnxModel(modelFile: YOLO_ModelFilePath, outputColumnNames: new[] { TinyYoloModelSettings.ModelOutput }, inputColumnNames: new[] { TinyYoloModelSettings.ModelInput })); var model = pipeline.Fit(trainData); using (var file = File.OpenWrite(ObjectDetectionModelFilePath)) mlContext.Model.Save(model, trainData.Schema, file); Console.WriteLine("Save Model success!"); }

  ImageNetData類定義以下:

    public class ImageNetData
    {
        [LoadColumn(0)]
        public string ImagePath;

        [LoadColumn(1)]
        public string Label;
    }

tags.tsv文件中僅包含一條樣本數據,由於模型已經訓練好,不存在再次訓練的意義。這裏只要放一張圖片樣本便可,經過Fit方法創建數據處理通道模型。

ApplyOnnxModel方法加載第三方ONNX模型,

    public struct TinyYoloModelSettings
    {
        // input tensor name
        public const string ModelInput = "image";

        // output tensor name
        public const string ModelOutput = "grid";
    }

 其中,輸入、輸出的列名稱是指定的。能夠經過安裝Netron這樣的工具來查詢ONNX文件的詳細信息,能夠看到輸入輸出的數據列名稱。


三、應用
        private static void LoadAndPredict()
        {
            var mlContext = new MLContext();

            ITransformer trainedModel;
            using (var stream = File.OpenRead(ObjectDetectionModelFilePath))
            {
                trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);               
            }
            var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(trainedModel);

            DirectoryInfo testdir = new DirectoryInfo(testimagesFolder);
            foreach (var jpgfile in testdir.GetFiles("*.jpg"))
            {  
                ImageNetData image = new ImageNetData
                {
                    ImagePath = jpgfile.FullName
                };               
var Predicted = predictionEngine.Predict(image); PredictImage(image.ImagePath, Predicted); } }
代碼遍歷一個文件夾下面的JPG文件。對每個文件進行轉換,得到預測結果。
ImageNetPrediction類定義以下:
    public class ImageNetPrediction
    {
        [ColumnName(TinyYoloModelSettings.ModelOutput)]
        public float[] PredictedLabels;       
    }

 輸出的「grid」列數據是一個float數組,不能直接理解其含義,因此須要經過代碼將其數據轉換爲便於理解的格式。

     YoloWinMlParser _parser = new YoloWinMlParser();
     IList<YoloBoundingBox> boundingBoxes = _parser.ParseOutputs(Predicted.PredictedLabels, 0.4f);            

YoloWinMlParser.ParseOutputs方法將float數組轉爲YoloBoundingBox對象的列表,第二個參數是可信度闕值,只輸出大於該可信度的數據。

YoloBoundingBox類定義以下:

    class YoloBoundingBox
    {    
        public string Label { get; set; }
        public float Confidence { get; set; }

        public float X { get; set; }
        public float Y { get; set; }
        public float Height { get; set; }
        public float Width { get; set; }
        public RectangleF Rect
        {
            get { return new RectangleF(X, Y, Width, Height); }
        }
    }

 其中:Label爲目標類型,Confidence爲可行程度。

因爲YOLO的特色致使對同一個目標會輸出多個一樣的檢測結果,因此還須要對檢測結果進行過濾,去掉那些高度重合的結果。

     YoloWinMlParser _parser = new YoloWinMlParser();
     IList<YoloBoundingBox> boundingBoxes = _parser.ParseOutputs(Predicted.PredictedLabels, 0.4f); 
     var filteredBoxes = _parser.NonMaxSuppress(boundingBoxes, 5, 0.6F);

 YoloWinMlParser.NonMaxSuppress第二個參數表示最多保留多少個結果,第三個參數表示重合率闕值,將去掉重合率大於該值的記錄。

 

4、資源獲取 

源碼下載地址:https://github.com/seabluescn/Study_ML.NET

工程名稱:YOLO_ObjectDetection

資源獲取:https://gitee.com/seabluescn/ML_Assets (ObjectDetection)

點擊查看機器學習框架ML.NET學習筆記系列文章目錄

相關文章
相關標籤/搜索