Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Naučte se používat ML.NET k detekci objektů v obrázcích pomocí modelu ONNX natrénovaného ve službě Microsoft Custom Vision.
Služba Microsoft Custom Vision je služba AI, která trénuje model na základě obrázků, které nahrajete. Model pak můžete exportovat do formátu ONNX a použít ho v ML.NET k předpovědím.
V tomto návodu se naučíte, jak:
- Vytvoření modelu ONNX pomocí služby Custom Vision
- Integrovat model ONNX do kanálu ML.NET
- Trénování modelu ML.NET
- Detekce znaků zastavení na testovacích obrázcích
Požadavky
- Visual Studio 2022 nebo novější
- Stáhněte si datovou sadu s 50 obrázky stop-sign.
- Účet Azure. Pokud ho nemáte, vytvořte si bezplatný účet Azure.
Vytvoření modelu
Vytvoření projektu Custom Vision
Přihlaste se ke službě Microsoft Custom Vision a vyberte Nový projekt.
V dialogovém okně Nový projekt vyplňte následující požadované položky:
- Nastavte název projektu Custom Vision jako StopSignDetection.
- Vyberte prostředek , který použijete. Jedná se o prostředek Azure, který se vytvoří pro projekt Custom Vision. Pokud žádný není uvedený, můžete ho vytvořit výběrem odkazu Vytvořit nový .
- Nastavte typ projektu jako rozpoznávání objektů.
- Nastavte typy klasifikace jako Více tříd, protože bude jedna třída na jeden obrázek.
- Nastavte doménu jako obecné (kompaktní) [S1]. Kompaktní doména umožňuje stáhnout model ONNX.
- U možností exportu vyberte základní platformy , které umožňují export modelu ONNX.
Po vyplnění výše uvedených polí vyberte Vytvořit projekt.
Přidání obrázků
- Po vytvoření projektu zvolte Přidat obrázky a začněte přidávat obrázky pro model, na který se má model trénovat. Vyberte obrázky stop-sign, které jste stáhli.
- Vyberte první obrázek, který se zobrazí. Na obrázku, který má model rozpoznat, můžete vybrat objekty. Vyberte značku stop v obrázku. Automaticky otevírané okno zobrazí a nastaví značku jako stop-sign.
- Opakujte pro všechny zbývající obrázky. Některé obrázky mají více než jedno znaménko zastavení, proto nezapomeňte označit všechny obrázky, které jsou na obrázcích.
Trénování modelu
Po nahrání a označení obrázků je teď možné model vytrénovat. Vyberte Trénovat.
Zobrazí se automaticky otevírané okno s dotazem, jaký typ trénování se má použít. Zvolte Rychlé trénování a pak vyberte Trénovat.
Stažení modelu ONNX
Po dokončení trénování klikněte na tlačítko Exportovat . Když se automaticky otevírané okno zobrazí, vyberte ONNX a stáhněte model ONNX.
Kontrola modelu ONNX
Rozbalte stažený soubor ONNX. Složka obsahuje několik souborů, ale dvě, které použijete v tomto kurzu, jsou:
- labels.txt, což je textový soubor obsahující popisky definované ve službě Custom Vision.
- model.onnx, což je model ONNX, který použijete k předpovědím v ML.NET.
K sestavení kanálu ML.NET budete potřebovat názvy vstupních a výstupních sloupců. K získání těchto informací použijte Netron, webovou a desktopovou aplikaci, která dokáže analyzovat modely ONNX a zobrazit jejich architekturu.
Při použití webové nebo desktopové aplikace Netron otevřete v aplikaci model ONNX. Po otevření se zobrazí graf. Tento graf vám řekne několik věcí, které budete potřebovat k sestavení kanálu ML.NET pro předpovědi.
Název vstupního sloupce – název vstupního sloupce vyžadovaný při použití modelu ONNX v ML.NET.
Název výstupního sloupce – název výstupního sloupce vyžadovaný při použití modelu ONNX v ML.NET.
Velikost obrázku – velikost požadovaná při změně velikosti obrázků v kanálu ML.NET.
Vytvoření projektu konzoly jazyka C#
V sadě Visual Studio vytvořte konzolovou aplikaci jazyka C# s názvem StopSignDetection. Jako cílovou architekturu zvolte .NET 8.
Nainstalujte pro projekt následující balíčky NuGet:
- Microsoft.ML
- Microsoft.ML.ImageAnalytics
- Microsoft.Onnx.Transformer
Poznámka:
Tato ukázka používá nejnovější stabilní verzi uvedených balíčků NuGet, pokud není uvedeno jinak.
Odkazování na model ONNX
V Průzkumníku řešení sady Visual Studio najděte dva soubory z modelu ONNX (labels.txt a model.onnx). Klikněte na ně pravým tlačítkem myši a v okně Vlastnosti nastavte Kopírovat do výstupního adresáře na Kopírovat pokud je novější.
Vytvoření vstupních a prediktivních tříd
Přidejte do projektu novou třídu a pojmenujte ji
StopSignInput. Pak do třídy přidejte následující strukturu:public struct ImageSettings { public const int imageHeight = 320; public const int imageWidth = 320; }Dále do třídy přidejte následující vlastnost.
public class StopSignInput { [ImageType(ImageSettings.imageHeight, ImageSettings.imageWidth)] public Bitmap Image { get; set; } }Vlastnost
Imageobsahuje rastrový obrázek použitý k predikci. AtributImageTypeudává ML.NET, že vlastnost je obrázek s rozměry 320x320, určený pomocí Netronu.Přidejte do projektu další třídu a pojmenujte ji
StopSignPrediction. Pak do třídy přidejte následující vlastnosti.public class StopSignPrediction { [ColumnName("detected_classes")] public long[] PredictedLabels { get; set; } [ColumnName("detected_boxes")] public float[] BoundingBoxes { get; set; } [ColumnName("detected_scores")] public float[] Scores { get; set; } }Vlastnost
PredictedLabelsobsahuje předpovědi popisků pro každý zjištěný objekt. Typ je plovoucí matice, takže každá položka v poli je předpověď každého popisku. AtributColumnNameML.NET říká, že tento sloupec v modelu je zadaný název, což jedetected_classes.Vlastnost
BoundingBoxesobsahuje ohraničující rámečky pro každý zjištěný objekt. Typ je plovoucí matice a každý zjištěný objekt se dodává se čtyřmi položkami v poli pro ohraničující pole. AtributColumnNameML.NET říká, že tento sloupec v modelu je zadaný název, což jedetected_boxes.Vlastnost
Scoresobsahuje skóre spolehlivosti každého předpovězeného objektu a jeho popisku. Typ je plovoucí matice, takže každá položka v poli je skóre spolehlivosti každého popisku. AtributColumnNameML.NET říká, že tento sloupec v modelu je zadaný název, což jedetected_scores.
Použití modelu k předpovědím
Přidejte příkazy using
Do souboru Program.cs přidejte na začátek souboru následující using direktivy.
using Microsoft.ML;
using Microsoft.ML.Transforms.Image;
using System.Drawing;
using WeatherRecognition;
Vytváření objektů
MLContextVytvořte objekt.var context = new MLContext();Vytvořte nový
IDataViewprázdnýStopSignInputseznam.var data = context.Data.LoadFromEnumerable(new List<StopSignInput>());Pro konzistenci uložte předpovězené obrázky do cesty sestavení.
var root = new FileInfo(typeof(Program).Assembly.Location); var assemblyFolderPath = root.Directory.FullName;
Sestavení kanálu
Když je vytvořený prázdný IDataView kanál, můžete ho vytvořit tak, aby mohl provádět předpovědi všech nových obrázků. Pipelina se skládá z několika kroků:
Změňte velikost příchozích obrázků.
Obrázek odesílaný do modelu pro predikci bude často v jiném poměru stran k obrázkům, které byly natrénovány na modelu. Pokud chcete zachovat konzistentní obraz pro přesné předpovědi, změňte velikost obrázku na 320x320. Uděláte to tak, že použijete metodu
ResizeImagesa nastavíteimageColumnNameji jako názevStopSignInput.Imagevlastnosti.var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: "image_tensor", imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight, inputColumnName: nameof(StopSignInput.Image))Extrahujte pixely obrázku.
Po změně velikosti obrázku je potřeba extrahovat pixely obrázku. Připojte metodu
ExtractPixelsdo kanálu a zadejte název sloupce pro výstup pixelů pro použití parametruoutputColumnName..Append(context.Transforms.ExtractPixels(outputColumnName: "image_tensor"))Vytvořte predikci použitím modelu ONNX na obrázku. To má několik parametrů:
- modelFile – cesta k souboru modelu ONNX
- outputColumnNames – pole řetězců obsahující názvy všech názvů výstupních sloupců, které lze najít při analýze modelu ONNX v Netronu.
- inputColumnNames – pole řetězců obsahující názvy všech názvů vstupních sloupců, které lze najít také při analýze modelu ONNX v Netronu.
Důležité
Používejte pouze modely z důvěryhodných zdrojů. Použití modelů z nedůvěryhodných zdrojů představuje bezpečnostní riziko.
.Append(context.Transforms.ApplyOnnxModel(outputColumnNames: new string[] { "detected_boxes", "detected_scores", "detected_classes" }, inputColumnNames: new string[] { "image_tensor" }, modelFile: "./Model/model.onnx"));
Přizpůsobení modelu
Teď, když jste definovali kanál, můžete ho použít k sestavení modelu ML.NET. Použijte metodu Fit v kanálu a předejte prázdnou IDataView.
var model = pipeline.Fit(data);
V dalším kroku použijte model k vytvoření prediktivního modulu. Jedná se o obecnou metodu, takže přebírá třídy StopSignInputStopSignPrediction , které byly vytvořeny dříve.
var predictionEngine = context.Model.CreatePredictionEngine<StopSignInput, StopSignPrediction>(model);
Extrahování popisků
Pokud chcete přiřadit výstupy modelu k jejich štítkům, musíte extrahovat štítky poskytované službou Custom Vision. Tyto popisky jsou v souborulabels.txt , který byl součástí souboru ZIP s modelem ONNX.
ReadAllLines Voláním metody přečtete všechny popisky, které tvoří soubor.
var labels = File.ReadAllLines("./model/labels.txt");
Předpověď na testovacím obrázku
Teď můžete model použít k predikci na nových obrázcích. V projektu je k dispozici testovací složka, kterou můžete použít k předpovědím. Tato složka obsahuje dva náhodné obrázky s dopravní značkou stop z Unsplash. Jeden obrázek má jedno znaménko zastavení, zatímco druhé má dvě značky stop. Použijte metodu GetFiles ke čtení cest k souborům obrázků v adresáři.
var testFiles = Directory.GetFiles("./test");
Projděte cesty k souborům, vytvořte predikci pomocí modelu a zobrazte výsledek.
Vytvořte smyčku
foreachpro procházení testovacích imagí.Bitmap testImage; foreach (var image in testFiles) { }foreachVe smyčce vygenerujte predikovaný název obrázku na základě názvu původního testovacího obrázku.var predictedImage = $"{Path.GetFileName(image)}-predicted.jpg";Také ve
foreachsmyčce vytvořteFileStreamimage a převeďte ji na .Bitmapusing (var stream = new FileStream(image, FileMode.Open)) { testImage = (Bitmap)Image.FromStream(stream); }foreachVe smyčce také volejte metoduPredictna prediktivním modulu.var prediction = predictionEngine.Predict(new StopSignInput { Image = testImage });Pomocí předpovědi můžete získat ohraničující rámečky. Chunk Pomocí metody určete, kolik objektů model zjistil. Uděláte to tak, že vezmete počet předpovídaných ohraničujících rámečků a vydělíte ho počtem popisků, které byly předpovězeny. Pokud jste například na obrázku rozpoznali tři objekty, bylo by v
BoundingBoxespoli zjištěno 12 položek a bylo by předpovězeno tři popisky. MetodaChunkby pak poskytla tři pole obsahující čtyři prvky, která reprezentují hraniční rámečky pro každý objekt.var boundingBoxes = prediction.BoundingBoxes.Chunk(prediction.BoundingBoxes.Count() / prediction.PredictedLabels.Count());Dále zachyťte původní šířku a výšku obrázků použitých pro predikci.
var originalWidth = testImage.Width; var originalHeight = testImage.Height;Výpočet místa na obrázku pro vykreslení polí Za tímto účelem vytvořte smyčku
forzaloženou na počtu bloků ohraničujících rámečků.for (int i = 0; i < boundingBoxes.Count(); i++) { }forVe smyčce vypočítejte pozici souřadnic x a y a šířku a výšku rámečku, které se mají na obrázku kreslit. První věcí, kterou musíte udělat, je získat sadu ohraničujících polí pomocíElementAtmetody.var boundingBox = boundingBoxes.ElementAt(i);Pomocí aktuálního ohraničujícího rámečku teď můžete vypočítat, kam chcete pole nakreslit. Použijte původní šířku obrázku pro první a třetí prvky ohraničujícího rámečku a původní výšku obrázku pro druhý a čtvrtý prvek.
var left = boundingBox[0] * originalWidth; var top = boundingBox[1] * originalHeight; var right = boundingBox[2] * originalWidth; var bottom = boundingBox[3] * originalHeight;Vypočítejte šířku a výšku pole, které se má nakreslit kolem zjištěného objektu v obrázku. Položky x a y jsou
lefthodnoty atopproměnné z předchozího výpočtu.Math.AbsPomocí metody získáte absolutní hodnotu z výpočtů šířky a výšky pro případ, že je záporná.var x = left; var y = top; var width = Math.Abs(right - left); var height = Math.Abs(top - bottom);Dále získáte predikovaný štítek z pole štítků.
var label = labels[prediction.PredictedLabels[i]];Pomocí metody vytvořte grafiku založenou na testovacím obrázku
Graphics.FromImage.using var graphics = Graphics.FromImage(testImage);Kreslete do obrázku pomocí informací o ohraničujícím rámečku. Nejprve nakreslete obdélník kolem detekovaných objektů pomocí
DrawRectanglemetody, která přebíráPenobjekt k určení barvy a šířky obdélníku, a předejtexmu ,y,widthaheightproměnné.graphics.DrawRectangle(new Pen(Color.NavajoWhite, 8), x, y, width, height);Pak zobrazte předpovězený popisek uvnitř pole metodou
DrawString, která přebírá řetězec k vytištění, aFontobjekt k určení, jak nakreslit řetězec a kam ho umístit.graphics.DrawString(label, new Font(FontFamily.Families[0], 18f), Brushes.NavajoWhite, x + 5, y + 5);Po smyčce
forzkontrolujte, jestli předpovězený soubor již existuje. Pokud ano, odstraňte ho. Pak ho uložte do definované výstupní cesty.if (File.Exists(predictedImage)) { File.Delete(predictedImage); } testImage.Save(Path.Combine(assemblyFolderPath, predictedImage));
Další kroky
Vyzkoušejte jeden z dalších kurzů klasifikace obrázků: