Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Meer informatie over het gebruik van ML.NET voor het detecteren van objecten in afbeeldingen met behulp van een ONNX-model dat is getraind in de Microsoft Custom Vision-service.
De Microsoft Custom Vision-service is een AI-service waarmee een model wordt getraind op basis van afbeeldingen die u uploadt. Vervolgens kunt u het model exporteren naar de ONNX-indeling en dit gebruiken in ML.NET om voorspellingen te doen.
In deze handleiding leer je hoe je:
- De Custom Vision-service gebruiken om een ONNX-model te maken
- Het ONNX-model opnemen in de ML.NET-pijplijn
- Het ML.NET-model trainen
- Stoptekens in testafbeeldingen detecteren
Vereiste voorwaarden
- Visual Studio 2022 of hoger.
- Download de gegevensset van 50 stoptekenafbeeldingen.
- Azure account Als u er nog geen hebt, maakt u een gratis Azure-account.
Het model maken
Het Custom Vision-project maken
Meld u aan bij de Microsoft Custom Vision-service en selecteer Nieuw project.
Vul in het dialoogvenster Nieuw project de volgende vereiste items in:
- Stel de naam van het Custom Vision-project in als StopSignDetection.
- Selecteer de resource die u gaat gebruiken. Dit is een Azure-resource die wordt gemaakt voor het Custom Vision-project. Als er geen wordt weergegeven, kunt u er een maken door de Nieuwe maken link te selecteren.
- Stel het projecttype in als objectdetectie.
- Stel de classificatietypen in als meerdere klassen omdat er één klasse per afbeelding is.
- Stel het domein in als Algemeen (compact) [S1]. Met het compacte domein kunt u het ONNX-model downloaden.
- Voor exportmogelijkheden selecteert u Basic-platformen om het exporteren van het ONNX-model toe te staan.
Zodra de bovenstaande velden zijn ingevuld, selecteert u Project maken.
Afbeeldingen toevoegen
- Wanneer het project is aangemaakt, kiest u Add images om afbeeldingen toe te voegen waarop het model kan trainen. Selecteer de stoptekenafbeeldingen die u hebt gedownload.
- Selecteer de eerste afbeelding die wordt weergegeven. U kunt objecten selecteren in de afbeelding die u wilt detecteren door het model. Selecteer het stop-teken in de afbeelding. In een pop-upvenster wordt de tag weergegeven en ingesteld als stop-teken.
- Herhaal dit voor alle resterende afbeeldingen. Sommige afbeeldingen hebben meer dan één stopteken, dus zorg ervoor dat u alle stoptekens in de afbeeldingen markeert.
Het model trainen
Nu de afbeeldingen zijn geüpload en getagd, kan het model nu worden getraind. Selecteer Trainen.
Er wordt een pop-upvenster weergegeven waarin wordt gevraagd welk type training moet worden gebruikt. Kies Snelle training en selecteer vervolgens Trainen.
Het ONNX-model downloaden
Zodra de training is voltooid, klikt u op de knop Exporteren . Wanneer het pop-upvenster wordt weergegeven, selecteert u ONNX om het ONNX-model te downloaden.
ONNX-model inspecteren
Pak het gedownloade ONNX-bestand uit. De map bevat verschillende bestanden, maar de twee die u in deze zelfstudie gaat gebruiken, zijn:
- labels.txt, een tekstbestand met de labels die zijn gedefinieerd in de Custom Vision-service.
- model.onnx, het ONNX-model dat u gebruikt om voorspellingen te doen in ML.NET.
Als u de ML.NET-pijplijn wilt bouwen, hebt u de namen van de namen van de invoer- en uitvoerkolommen nodig. Als u deze informatie wilt ophalen, gebruikt u Netron, een web - en desktop-app die ONNX-modellen kan analyseren en hun architectuur kan weergeven.
Wanneer u de web- of bureaublad-app van Netron gebruikt, opent u het ONNX-model in de app. Zodra deze is geopend, wordt er een grafiek weergegeven. In deze grafiek ziet u enkele dingen die u nodig hebt om de ML.NET-pijplijn te bouwen voor voorspellingen.
Naam van invoerkolom : de naam van de invoerkolom die is vereist bij het toepassen van het ONNX-model in ML.NET.
Naam van uitvoerkolom : de naam van de uitvoerkolom die is vereist bij het toepassen van het ONNX-model in ML.NET.
Afbeeldingsgrootte: de grootte die is vereist bij het resizen van afbeeldingen in de ML.NET-pijplijn.
Een C#-consoleproject maken
Maak in Visual Studio een C#-consoletoepassing met de naam 'StopSignDetection'. Kies .NET 8 als doelframework.
Installeer de volgende NuGet-pakketten voor het project:
- Microsoft.ML
- Microsoft.ML.ImageAnalytics
- Microsoft.Onnx.Transformer
Opmerking
In dit voorbeeld wordt de laatste stabiele versie van de vermelde NuGet-pakketten gebruikt, tenzij anders vermeld.
Verwijzen naar het ONNX-model
Zoek de twee bestanden uit het ONNX-model (labels.txt en model.onnx) in Visual Studio Solution Explorer. Klik er met de rechtermuisknop op en stel in het venster Eigenschappen Kopiëren naar uitvoermap in op Kopiëren indien nieuwer.
Invoer- en voorspellingsklassen maken
Voeg een nieuwe klasse toe aan uw project en geef deze een
StopSignInputnaam. Voeg vervolgens de volgende struct toe aan de klasse:public struct ImageSettings { public const int imageHeight = 320; public const int imageWidth = 320; }Voeg vervolgens de volgende eigenschap toe aan de klasse.
public class StopSignInput { [ImageType(ImageSettings.imageHeight, ImageSettings.imageWidth)] public Bitmap Image { get; set; } }De
Imageeigenschap bevat de bitmap van de afbeelding die wordt gebruikt voor voorspelling. HetImageTypekenmerk vertelt ML.NET dat de eigenschap een afbeelding is met dimensies 320 en 320, die is bepaald met behulp van Netron.Voeg een andere klasse toe aan uw project en geef deze een
StopSignPredictionnaam. Voeg vervolgens de volgende eigenschappen toe aan de klasse.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; } }De
PredictedLabelseigenschap bevat de voorspellingen van labels voor elk gedetecteerd object. Het type is een floatmatrix, dus elk item in de matrix is de voorspelling van elk label. HetColumnNamekenmerk vertelt ML.NET dat deze kolom in het model de naam is die is opgegeven alsdetected_classes.De
BoundingBoxeseigenschap bevat de begrenzingsvakken voor elk gedetecteerd object. Het type is een floatmatrix en elk gedetecteerd object bevat vier items in de matrix voor het begrenzingsvak. HetColumnNamekenmerk vertelt ML.NET dat deze kolom in het model de naam bevat die is opgegeven alsdetected_boxes.De
Scoreseigenschap bevat de betrouwbaarheidsscores van elk voorspeld object en het bijbehorende label. Het type is een floatmatrix, dus elk item in de matrix is de betrouwbaarheidsscore van elk label. HetColumnNameattribuut geeft aan ML.NET door dat deze kolom in het model de opgegeven naamdetected_scoresheeft.
Het model gebruiken om voorspellingen te doen
Gebruiksrichtlijnen toevoegen
Voeg in het bestand Program.cs de volgende using instructies toe aan het begin van het bestand.
using Microsoft.ML;
using Microsoft.ML.Transforms.Image;
using System.Drawing;
using WeatherRecognition;
Objecten maken
Maak het
MLContextobject.var context = new MLContext();Maak een
IDataViewmet een nieuwe legeStopSignInputlijst.var data = context.Data.LoadFromEnumerable(new List<StopSignInput>());Voor consistentie slaat u de voorspelde afbeeldingen op in het assemblypad.
var root = new FileInfo(typeof(Program).Assembly.Location); var assemblyFolderPath = root.Directory.FullName;
De pijplijn bouwen
Met de lege IDataView aangemaakt, kan de pijplijn worden gebouwd om voorspellingen voor nieuwe afbeeldingen uit te voeren. De pijplijn bestaat uit verschillende stappen:
Pas het formaat van de binnenkomende afbeeldingen aan.
De afbeelding die wordt verzonden naar het model voor voorspelling, heeft vaak een andere hoogte-breedteverhouding dan de afbeeldingen die op het model zijn getraind. Als u de afbeelding consistent wilt houden voor nauwkeurige voorspellingen, wijzigt u het formaat van de afbeelding in 320x320. Hiervoor gebruikt u de
ResizeImagesmethode en stelt u deimageColumnNamenaam van deStopSignInput.Imageeigenschap in.var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: "image_tensor", imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight, inputColumnName: nameof(StopSignInput.Image))Pak de pixels van de afbeelding uit.
Nadat het formaat van de afbeelding is gewijzigd, moet u de pixels extraheren. Voeg de
ExtractPixelsmethode toe aan uw pijplijn en geef de naam van de kolom op om de pixels uit te voeren met behulp van deoutputColumnNameparameter..Append(context.Transforms.ExtractPixels(outputColumnName: "image_tensor"))Pas het ONNX-model toe op de afbeelding om een voorspelling te doen. Hiervoor zijn enkele parameters nodig:
- modelFile : het pad naar het ONNX-modelbestand
- outputColumnNames : een tekenreeksmatrix met de namen van alle namen van de uitvoerkolommen, die u kunt vinden bij het analyseren van het ONNX-model in Netron.
- inputColumnNames : een tekenreeksmatrix met de namen van alle naam van de invoerkolom, die ook kan worden gevonden bij het analyseren van het ONNX-model in Netron.
.Append(context.Transforms.ApplyOnnxModel(outputColumnNames: new string[] { "detected_boxes", "detected_scores", "detected_classes" }, inputColumnNames: new string[] { "image_tensor" }, modelFile: "./Model/model.onnx"));
Het model aanpassen
Nu u een pijplijn hebt gedefinieerd, kunt u deze gebruiken om het ML.NET model te bouwen. Gebruik de Fit methode in de pijplijn en geef de lege IDataViewdoorvoer door.
var model = pipeline.Fit(data);
Als u vervolgens voorspellingen wilt doen, gebruikt u het model om een voorspellingsengine te maken. Dit is een algemene methode, dus accepteert deze de StopSignInput-klasse en de StopSignPrediction-klasse die eerder zijn gemaakt.
var predictionEngine = context.Model.CreatePredictionEngine<StopSignInput, StopSignPrediction>(model);
De labels extraheren
Om de uitvoer van het model aan de labels toe te wijzen, moet u de door Custom Vision geleverde labels extraheren. Deze labels bevinden zich in het labels.txt-bestand dat is opgenomen in het zip-bestand met het ONNX-model.
Roep de ReadAllLines methode aan om alle labels van het bestand te lezen.
var labels = File.ReadAllLines("./model/labels.txt");
Voorspellen op een testafbeelding
U kunt nu het model gebruiken om nieuwe afbeeldingen te voorspellen. In het project is er een testmap die u kunt gebruiken om voorspellingen te doen. Deze map bevat twee willekeurige afbeeldingen die een stopbord bevatten vanuit Unsplash. Eén afbeelding heeft één stopteken terwijl de andere twee stoptekens heeft. Gebruik de GetFiles methode om de bestandspaden van de afbeeldingen in de map te lezen.
var testFiles = Directory.GetFiles("./test");
Loop door de bestandspaden om een voorspelling te doen met het model en voer het resultaat uit.
Maak een
foreachlus om de testafbeeldingen te doorlopen.Bitmap testImage; foreach (var image in testFiles) { }Genereer in de
foreachlus de voorspelde afbeeldingsnaam op basis van de naam van de oorspronkelijke testafbeelding.var predictedImage = $"{Path.GetFileName(image)}-predicted.jpg";Maak ook in de
foreachlus eenFileStreamvan het image en zet deze om naar eenBitmap.using (var stream = new FileStream(image, FileMode.Open)) { testImage = (Bitmap)Image.FromStream(stream); }Roep ook in de
foreachlus dePredictmethode aan op de voorspellingsengine.var prediction = predictionEngine.Predict(new StopSignInput { Image = testImage });Met de voorspelling kunt u de omsluitende kaders verkrijgen. Gebruik de Chunk methode om te bepalen hoeveel objecten het model heeft gedetecteerd. Doe dit door het aantal voorspelde begrenzingsvakken te nemen en dat te delen door het aantal labels dat is voorspeld. Als er bijvoorbeeld drie objecten in een afbeelding zijn gedetecteerd, zijn er 12 items in de
BoundingBoxesmatrix en drie labels voorspeld. DeChunkmethode geeft u vervolgens drie matrices van vier om de begrenzingsvakken voor elk object weer te geven.var boundingBoxes = prediction.BoundingBoxes.Chunk(prediction.BoundingBoxes.Count() / prediction.PredictedLabels.Count());Leg vervolgens de oorspronkelijke breedte en hoogte vast van de afbeeldingen die worden gebruikt voor voorspelling.
var originalWidth = testImage.Width; var originalHeight = testImage.Height;Bereken waar in de afbeelding de vakken moeten worden getekend. Maak hiervoor een
forlus op basis van het aantal begrenzingsvakken.for (int i = 0; i < boundingBoxes.Count(); i++) { }Bereken binnen de
forlus de positie van de x- en y-coördinaten, evenals de breedte en hoogte van het vak om op de afbeelding te tekenen. Het eerste dat u moet doen, is de set begrenzingsboxen ophalen met behulp van deElementAtmethode.var boundingBox = boundingBoxes.ElementAt(i);Met de huidige begrenzingsbox kunt u nu berekenen waar het vak getekend moet worden. Gebruik de oorspronkelijke afbeeldingsbreedte voor het eerste en derde element van het begrenzingsvak en de oorspronkelijke afbeeldingshoogte voor het tweede en vierde element.
var left = boundingBox[0] * originalWidth; var top = boundingBox[1] * originalHeight; var right = boundingBox[2] * originalWidth; var bottom = boundingBox[3] * originalHeight;Bereken de breedte en de hoogte van het vak om rond het gedetecteerde object in de afbeelding te tekenen. De x- en y-items zijn de
leftentopvariabelen uit de vorige berekening. Gebruik deMath.Absmethode om de absolute waarde op te halen uit de berekeningen voor breedte en hoogte voor het geval dit negatief is.var x = left; var y = top; var width = Math.Abs(right - left); var height = Math.Abs(top - bottom);Haal vervolgens het voorspelde label op uit de matrix met labels.
var label = labels[prediction.PredictedLabels[i]];Maak een afbeelding op basis van de testafbeelding met behulp van de
Graphics.FromImagemethode.using var graphics = Graphics.FromImage(testImage);Teken op de afbeelding met behulp van de informatie in het omkaderingsvak. Teken eerst de rechthoek rond de gedetecteerde objecten met behulp van de
DrawRectanglemethode die eenPenobject gebruikt om de kleur en breedte van de rechthoek te bepalen en geef dex,y, enwidthheightvariabelen door.graphics.DrawRectangle(new Pen(Color.NavajoWhite, 8), x, y, width, height);Geef vervolgens het voorspelde label in het vak weer met de
DrawStringmethode die de tekenreeks inneemt om af te drukken en eenFontobject om te bepalen hoe de tekenreeks moet worden getekend en waar deze moet worden geplaatst.graphics.DrawString(label, new Font(FontFamily.Families[0], 18f), Brushes.NavajoWhite, x + 5, y + 5);Controleer na de
forlus of het voorspelde bestand al bestaat. Als dit het geval is, verwijdert u deze. Sla het vervolgens op in het gedefinieerde uitvoerpad.if (File.Exists(predictedImage)) { File.Delete(predictedImage); } testImage.Save(Path.Combine(assemblyFolderPath, predictedImage));
Volgende stappen
Probeer een van de andere zelfstudies voor afbeeldingsclassificatie: