Megosztás a következőn keresztül:


Oktatóanyag: Kép kategorizálása ML.NET-ben a Custom Vision ONNX-modell alapján

Megtudhatja, hogyan használhatja a ML.NET a képek objektumainak észlelésére a Microsoft Custom Vision szolgáltatásban betanított ONNX-modellel.

A Microsoft Custom Vision szolgáltatás egy AI-szolgáltatás, amely a feltöltött képek alapján tanít be egy modellt. Ezután exportálhatja a modellt ONNX formátumba, és a ML.NET használatával előrejelzéseket készíthet.

Ebben az oktatóanyagban a következőket sajátíthatja el:

  • ONNX-modell létrehozása a Custom Vision szolgáltatással
  • Az ONNX-modell beépítése a ML.NET folyamatba
  • A ML.NET modell betanítása
  • Stop-jelek észlelése tesztképekben

Előfeltételek

A modell létrehozása

A Custom Vision-projekt létrehozása

Jelentkezzen be a Microsoft Custom Vision szolgáltatásba, és válassza Új projektlehetőséget.

Az Új projekt párbeszédpanelen töltse ki a következő kötelező elemeket:

  • Állítsa be a Custom Vision-projekt neveStopSignDetection.
  • Válassza ki a -es erőforrást, amelyet használni fog. Ez egy Azure-erőforrás, amely a Custom Vision-projekthez lesz létrehozva. Ha egyik sem szerepel a listában, létrehozhat egyet az Új létrehozása hivatkozás kiválasztásával.
  • Állítsa be a projekttípust objektumészlelésként .
  • Állítsa be a besorolási típusokattöbbosztályos, mivel képenként egy osztály lesz.
  • Állítsa be a(z) tartományt a Általános (kompakt) [S1]beállításra. A kompakt tartomány lehetővé teszi az ONNX-modell letöltését.
  • Az Exportálási képességekaz ONNX-modell exportálásának engedélyezéséhez válassza Alapszintű platformok lehetőséget.

A fenti mezők kitöltése után válassza a Projekt létrehozásalehetőséget.

Képek hozzáadása

  1. A projekt létrehozása után válassza a Képek hozzáadása opciót, hogy elkezdje hozzáadni a model betanításához szükséges képeket. Válassza ki a letöltött stop-sign képeket.
  2. Válassza ki az első megjelenített képet. A képen kijelölheti azokat az objektumokat, amelyeket a modell észlelni szeretne. Válassza ki a stop táblát a képen. Egy felugró ablak megjeleníti és beállítja a címkét stop-sign.
  3. Ismételje meg az összes többi képnél. Egyes képek több stopjelet is tartalmaznak, ezért mindenképpen jelöljön meg mindent, ami a képeken található.

A modell betanítása

A feltöltött és címkézett képek után a modell betanítása is elvégezhető. Válassza Vonatot.

Megjelenik egy előugró ablak, amely megkérdezi, hogy milyen típusú betanítást használjon. Válassza a Gyors betanítás, majd a Betanításlehetőséget.

Az ONNX-modell letöltése

A betanítás befejezése után kattintson az Exportálás gombra. Amikor megjelenik az előugró ablak, válassza ONNX az ONNX-modell letöltéséhez.

ONNX-modell vizsgálata

Bontsa ki a letöltött ONNX-fájlt. A mappa több fájlt tartalmaz, de az oktatóanyagban használt kettő a következő:

  • labels.txt, amely a Custom Vision szolgáltatásban definiált címkéket tartalmazó szövegfájl.
  • model.onnx, amely az ONNX-modell, amellyel előrejelzéseket készíthet ML.NET.

A ML.NET folyamat létrehozásához szüksége lesz a bemeneti és kimeneti oszlopnevek nevére. Az információk beszerzéséhez használja a Netront, egy webes és asztali alkalmazást, amely képes elemezni az ONNX-modelleket, és bemutatni azok architektúráját.

  1. Ha a Netron webes vagy asztali alkalmazását használja, nyissa meg az ONNX-modellt az alkalmazásban. Miután megnyílik, megjelenik egy gráf. Ez a gráf elárul néhány dolgot, amelyekre szüksége lesz az előrejelzésekhez az ML.NET adatfolyam létrehozásához.

    • Bemeneti oszlop neve – Az ONNX-modell ML.NET való alkalmazásakor szükséges bemeneti oszlopnév.

      Netron bemeneti oszlop

    • Kimeneti oszlop neve – Az ONNX-modell ML.NET való alkalmazásakor szükséges kimeneti oszlopnév.

      Netron kimeneti oszlop

    • képméret – A képek átméretezéséhez szükséges méret a ML.NET folyamatban.

      Netron képméret

C#-konzolprojekt létrehozása

  1. A Visual Studióban hozzon létre egy "StopSignDetection" nevű C#-konzolalkalmazást. Válassza a .NET 8-at cél-keretrendszerként.

  2. Telepítse a következő NuGet-csomagokat a projekthez:

    • Microsoft.ML
    • Microsoft.ML.ImageAnalytics
    • Microsoft.Onnx.Transformer

    Jegyzet

    Ez a minta az említett NuGet-csomagok legújabb stabil verzióját használja, hacsak másként nem rendelkezik.

Referencia az ONNX-modellre

Keresse meg az ONNX-modell két fájlját (labels.txt és model.onnx) a Visual Studio Solution Explorer. Kattintson rájuk a jobb gombbal, és a Tulajdonságok ablakban állítsa be a Másolás kimeneti könyvtárbaMásolás, ha újabb.

Bemeneti és előrejelzési osztályok létrehozása

  1. Adjon hozzá egy új osztályt a projekthez, és nevezze el StopSignInput. Ezután adja hozzá a következő strukturát az osztályhoz:

    public struct ImageSettings
    {
        public const int imageHeight = 320;
        public const int imageWidth = 320;
    }
    
  2. Ezután adja hozzá a következő tulajdonságot az osztályhoz.

    public class StopSignInput
    {
        [ImageType(ImageSettings.imageHeight, ImageSettings.imageWidth)]
        public Bitmap Image { get; set; }
    }
    

    A Image tulajdonság az előrejelzéshez használt kép bitképét tartalmazza. Az ImageType attribútum azt jelzi az ML.NET számára, hogy a tulajdonság egy 320 x 320 méretű kép, amit a Netron segítségével állapítottak meg.

  3. Adjon hozzá egy másik osztályt a projekthez, és nevezze el StopSignPrediction. Ezután adja hozzá a következő tulajdonságokat az osztályhoz.

    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; }
    }
    

    A PredictedLabels tulajdonság az egyes észlelt objektumok címkéinek előrejelzéseit tartalmazza. A típus egy lebegőpontos tömb, így a tömb minden eleme az egyes címkék előrejelzése. A ColumnName attribútum azt jelzi, hogy az ML.NET modell ezen oszlopának a neve, amelyet megadtak, detected_classes.

    Minden észlelt objektumhoz a BoundingBoxes tulajdonság tartalmazza a határoló kereteket. A típus egy lebegőpontos tömb, és minden észlelt objektum négy elemmel érkezik a tömbben a határoló dobozhoz. A ColumnName attribútum azt jelzi, hogy az ML.NET modell ezen oszlopának a neve, amelyet megadtak, detected_boxes.

    A Scores tulajdonság az egyes előrejelzett objektumok megbízhatósági pontszámait és címkéjét tartalmazza. A típus egy lebegőpontos tömb, így a tömb minden eleme az egyes címkék megbízhatósági pontszáma. A ColumnName attribútum azt jelzi, hogy az ML.NET modell ezen oszlopának a neve, amelyet megadtak, detected_scores.

Előrejelzések készítése a modell használatával

Használati direktívák hozzáadása

A Program.cs fájlban adja hozzá a következő using irányelveket a fájl elejéhez.

using Microsoft.ML;
using Microsoft.ML.Transforms.Image;
using System.Drawing;
using WeatherRecognition;

Objektumok létrehozása

  1. Hozza létre a MLContext objektumot.

    var context = new MLContext();
    
  2. Hozzon létre egy IDataView-at egy új üres StopSignInput lista segítségével.

    var data = context.Data.LoadFromEnumerable(new List<StopSignInput>());
    
  3. A konzisztencia érdekében mentse az előrejelzett képeket az összeállítás útvonalára.

    var root = new FileInfo(typeof(Program).Assembly.Location);
    var assemblyFolderPath = root.Directory.FullName;
    

A csővezeték kiépítése

Az üres IDataView létrehozásával a pipeline felépíthető, hogy bármilyen új kép előrejelzéséhez használható legyen. A folyamat több lépésből áll:

  1. Méretezze át a bejövő képeket.

    Az előrejelzés céljából a modellnek küldött kép gyakran eltérő méretarányban jelenik meg a modellen betanított képekhez viszonyítva. Ha a kép egységes marad a pontos előrejelzésekhez, méretezze át a képet 320x320-ra. Ehhez használja a ResizeImages metódust, és állítsa be a imageColumnName a StopSignInput.Image tulajdonság neveként.

    var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: "image_tensor", imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight, inputColumnName: nameof(StopSignInput.Image))
    
  2. Bontsa ki a kép képpontjait.

    A kép átméretezése után ki kell nyernie a kép képpontjait. Fűzze hozzá a ExtractPixels metódust a folyamathoz, és adja meg annak az oszlopnak a nevét, amely a képpontokat a outputColumnName paraméter használatával adja meg.

    .Append(context.Transforms.ExtractPixels(outputColumnName: "image_tensor"))
    
  3. Az ONNX-modell alkalmazása a képre előrejelzés készítéséhez. Ez néhány paramétert vesz igénybe:

    • modelFile – Az ONNX-modellfájl elérési útja
    • outputColumnNames – Az összes kimeneti oszlop nevének nevét tartalmazó karakterlánctömb, amely a Netronban található ONNX-modell elemzésekor található.
    • inputColumnNames – Az összes bemeneti oszlop nevének nevét tartalmazó karakterlánctömb, amely a NetronBAN található ONNX-modell elemzésekor is megtalálható.
    .Append(context.Transforms.ApplyOnnxModel(outputColumnNames: new string[] { "detected_boxes", "detected_scores", "detected_classes" }, inputColumnNames: new string[] { "image_tensor" }, modelFile: "./Model/model.onnx"));
    

A modell igazítása

Most, hogy definiált egy folyamatot, használhatja a ML.NET modell létrehozásához. Használja a Fit metódust a pipeline-on, és adja át az üres IDataView-et.

var model = pipeline.Fit(data);

Az előrejelzések készítéséhez használja a modellt egy előrejelzési motor létrehozásához. Ez egy általános módszer, ezért a korábban létrehozott StopSignInput és StopSignPrediction osztályokat veszi igénybe.

var predictionEngine = context.Model.CreatePredictionEngine<StopSignInput, StopSignPrediction>(model);

A címkék kinyerése

Ahhoz, hogy a modell kimeneteit a címkéihez rendelje, ki kell nyernie a Custom Vision által biztosított címkéket. Ezek a címkék az ONNX-modell zip-fájljában található labels.txt fájlban találhatók.

Hívja meg a ReadAllLines metódust a fájl összes címkéjének olvasásához.

var labels = File.ReadAllLines("./model/labels.txt");

Előrejelzés tesztképen

Most már használhatja a modellt az új képek előrejelzésére. A projektben van egy teszt mappa, amellyel előrejelzéseket készíthet. Ez a mappa két véletlenszerű képet tartalmaz egy stop táblával az Unsplash-ről . Az egyik kép egy leállításjellel, a másik pedig két stopjellel rendelkezik. A GetFiles metódus használatával olvassa el a könyvtárban lévő képek fájlútvonalait.

var testFiles = Directory.GetFiles("./test");

Futtasd végig a fájl elérési útjait, hogy a modellel előrejelzést készíts, és jelenítsd meg az eredményt.

  1. Hozzon létre egy foreach hurkot a tesztképeken való végigiteráláshoz.

    Bitmap testImage;
    
    foreach (var image in testFiles)
    {
    
    }
    
  2. A foreach ciklusban hozza létre a várható kép nevét az eredeti tesztkép neve alapján.

    var predictedImage = $"{Path.GetFileName(image)}-predicted.jpg";
    
  3. A foreach hurokban hozzon létre egy FileStream-et a képből, és konvertálja egy Bitmap-vé.

    using (var stream = new FileStream(image, FileMode.Open))
    {
        testImage = (Bitmap)Image.FromStream(stream);
    }
    
  4. A foreach hurokban is hívja meg a Predict metódust az előrejelzési motoron.

    var prediction = predictionEngine.Predict(new StopSignInput { Image = testImage });
    
  5. Előrejelzéssel megkaphatja a határolókereteket. A Chunk metódus használatával meghatározhatja, hogy a modell hány objektumot észlelt. Ezt úgy teheti meg, hogy figyelembe veszi az előrejelzett határolókeretek számát, és elosztja azt az előrejelzett címkék számával. Ha például három objektumot észlelt egy képen, akkor a BoundingBoxes tömbben 12 elem és három címke van előre jelezve. A Chunk metódus ezután három négy tömböt adna az egyes objektumokhoz tartozó határolókeretek megjelenítéséhez.

    var boundingBoxes = prediction.BoundingBoxes.Chunk(prediction.BoundingBoxes.Count() / prediction.PredictedLabels.Count());
    
  6. Ezután rögzítse az előrejelzéshez használt képek eredeti szélességét és magasságát.

    var originalWidth = testImage.Width;
    var originalHeight = testImage.Height;
    
  7. Számítsa ki, hogy a képen hol rajzolja meg a mezőket. Ehhez hozzon létre egy for hurkot a határolókeretek száma alapján.

    for (int i = 0; i < boundingBoxes.Count(); i++)
    {
    }
    
  8. A for hurokban számítsa ki az x és y koordináták pozícióját, valamint a doboz szélességét és magasságát a kép rajzolásához. Az első teendő a határolókeretek készletének lekérése a ElementAt metódus használatával.

    var boundingBox = boundingBoxes.ElementAt(i);
    
  9. Az aktuális határolókerettel mostantól kiszámíthatja, hogy hová kell rajzolni a dobozt. Használja a határolókeret első és harmadik elemének eredeti képszélességét, a második és negyedik elem eredeti képmagasságát.

    var left = boundingBox[0] * originalWidth;
    var top = boundingBox[1] * originalHeight;
    var right = boundingBox[2] * originalWidth;
    var bottom = boundingBox[3] * originalHeight;
    
  10. Számítsa ki a doboz szélességét és magasságát, hogy a képen belül az észlelt objektum körül rajzoljon. Az x és y elemek az előző számítás left és top változói. A Math.Abs metódus használatával lekérheti az abszolút értéket a szélesség- és magasságszámításból, ha az negatív.

    var x = left;
    var y = top;
    var width = Math.Abs(right - left);
    var height = Math.Abs(top - bottom);
    
  11. Ezután szerezze meg az előrejelzett címkét a címkék tömbjéből.

    var label = labels[prediction.PredictedLabels[i]];
    
  12. Hozzon létre egy ábrát a tesztkép alapján a Graphics.FromImage metódus használatával.

    using var graphics = Graphics.FromImage(testImage);
    
  13. Rajzoljon a képre a megadott határolókeret használatával. Először rajzolja meg a téglalapot az észlelt objektumok köré azzal a DrawRectangle metódussal, amely egy Pen objektumban határozza meg a téglalap színét és szélességét, majd adja meg a x, y, widthés height változókat.

    graphics.DrawRectangle(new Pen(Color.NavajoWhite, 8), x, y, width, height);
    
  14. Ezután jelenítse meg az előrejelzett címkét a mezőben a DrawString metódussal, amely beolvassa a kinyomtatandó sztringet, és egy Font objektummal meghatározza, hogyan rajzolja meg a sztringet, és hová helyezze el.

    graphics.DrawString(label, new Font(FontFamily.Families[0], 18f), Brushes.NavajoWhite, x + 5, y + 5);
    
  15. A for ciklus után ellenőrizze, hogy az előrejelzett fájl már létezik-e. Ha igen, törölje. Ezután mentse a megadott kimeneti elérési útra.

    if (File.Exists(predictedImage))
    {
        File.Delete(predictedImage);
    }
    
    testImage.Save(Path.Combine(assemblyFolderPath, predictedImage));
    

Következő lépések

Próbálkozzon a többi képbesorolási oktatóanyag egyikével: