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)