Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Megtudhatja, hogyan használhat előre betanított ONNX-modellt ML.NET a képek objektumainak észleléséhez.
Az objektumészlelési modell alapoktól való betanításához több millió paramétert, nagy mennyiségű címkézett betanítási adatot és nagy mennyiségű számítási erőforrást (több száz GPU-órát) kell beállítani. Az előre betanított modell használatával parancsikont adhat a betanítási folyamatnak.
Ebben az oktatóanyagban a következőket sajátíthatja el:
- A probléma ismertetése
- Ismerje meg, mi az ONNX, és hogyan működik ML.NET
- A modell megismerése
- Az előre betanított modell újrafelhasználása
- Betöltött modellel rendelkező objektumok észlelése
Előfeltételek
- Visual Studio 2022 vagy újabb verzió.
- Microsoft.ML NuGet-csomag
- Microsoft.ML.ImageAnalytics NuGet-csomag
- Microsoft.ML.OnnxTransformer NuGet-csomag
- Tiny YOLOv2 előre betanított modell
- Netron (nem kötelező)
ONNX objektumészlelési minta áttekintése
Ez a minta egy .NET core konzolalkalmazást hoz létre, amely egy előre betanított mélytanulási ONNX-modellel észleli a képeken belüli objektumokat. A minta kódja a GitHub dotnet/machinelearning-samples adattárában található.
Mi az objektumészlelés?
Az objektumészlelés számítógépes látási probléma. Bár szorosan kapcsolódik a képbesoroláshoz, az objektumészlelés részletesebb léptékben végzi el a képbesorolást. Az objektumészlelés egyaránt megkeresi és kategorizálja az entitásokat a képeken belül. Az objektumészlelési modelleket általában mélytanulási és neurális hálózatokkal tanítják be. További információt a mély tanulás és a gépi tanulás című témakörben talál.
Objektumészlelést akkor használjon, ha a képek több különböző típusú objektumot tartalmaznak.
Az objektumészlelés néhány használati esete:
- Önvezető autók
- Robotika
- Arcfelismerés
- Munkahelyi biztonság
- Objektumszámlálás
- Tevékenységfelismerés
Mélytanulási modell kiválasztása
A mély tanulás a gépi tanulás egy részhalmaza. A mélytanulási modellek betanítása érdekében nagy mennyiségű adatra van szükség. Az adatok mintáit rétegek sorozata képviseli. Az adatokban lévő kapcsolatok a súlyokat tartalmazó rétegek közötti kapcsolatokként vannak kódolva. Minél nagyobb a súly, annál erősebb a kapcsolat. A rétegek és kapcsolatok sorozatát együttesen mesterséges neurális hálózatoknak nevezzük. Minél több réteg van egy hálózatban, annál "mélyebb", így mély neurális hálózat.
A neurális hálózatoknak különböző típusai vannak, a leggyakoribbak a többrétegű perceptron (MLP), a konvolúciós neurális hálózat (CNN) és a Recurrent Neural Network (RNN). A legalapvetőbb az MLP, amely bemenetek halmazát képezi le egy halmaz kimenetekre. Ez a neurális hálózat akkor jó, ha az adatok nem rendelkeznek térbeli vagy időösszetevővel. A CNN konvolúciós rétegeket használ az adatokban található térbeli információk feldolgozásához. A CNN-ek esetében jó példa a képfeldolgozás egy funkció jelenlétének észlelésére egy kép egy régiójában (például van orra a kép közepén?). Végül az RNN-k lehetővé teszik az állapot vagy a memória megőrzését bemenetként. Az RNN-eket idősorozat-elemzéshez használják, ahol fontos az események sorrendje és kontextusa.
A modell megismerése
Az objektumészlelés képfeldolgozási feladat. Ezért a probléma megoldására betanított mélytanulási modellek többsége CNN-eket jelent. Az oktatóanyagban használt modell a Pici YOLOv2 modell, amely a tanulmányban leírt YOLOv2 modell kompaktabb verziója: "YOLO9000: Better, Faster, Stronger" by Redmon and Farhadi. Az apró YOLOv2 a Pascal VOC adatkészleten van betanítve, és 15 rétegből áll, amelyek 20 különböző objektumosztály előrejelzésére képesek. Mivel a Tiny YOLOv2 az eredeti YOLOv2 modell sűrített verziója, a sebesség és a pontosság közötti kompromisszum jön létre. A modellt alkotó különböző rétegek a Netronhoz hasonló eszközökkel jeleníthetők meg. A modell vizsgálata a neurális hálózatot alkotó összes réteg közötti kapcsolatok leképezését eredményezné, ahol minden réteg tartalmazza a réteg nevét és a megfelelő bemenet /kimenet dimenzióit. A modell bemeneteinek és kimeneteinek leírására használt adatstruktúrákat tenzoroknak nevezzük. A Tensorok olyan tárolókként is felfoghatók, amelyek N dimenziókban tárolják az adatokat. A Tiny YOLOv2 esetében a bemeneti réteg neve, image és a dimenziók 3 x 416 x 416tenzorára számít. A kimeneti réteg neve a grid dimenziók 125 x 13 x 13kimeneti tenzorát hozza létre.
A YOLO-modell egy képet 3(RGB) x 416px x 416pxkészít. A modell ezt a bemenetet használja, és átadja a különböző rétegeken a kimenet létrehozásához. A bemeneti képet a kimenet 13 x 13 rácsra osztja, és a rács minden cellája 125 értékeket tartalmaz.
Mi az ONNX-modell?
Az Open Neural Network Exchange (ONNX) egy nyílt forráskódú formátum az AI-modellekhez. Az ONNX támogatja a keretrendszerek közötti interoperabilitást. Ez azt jelenti, hogy betaníthat egy modellt az olyan népszerű gépi tanulási keretrendszerek egyikében, mint a PyTorch, átalakíthatja ONNX formátumba, és felhasználhatja az ONNX-modellt egy másik keretrendszerben, például ML.NET. További információért látogasson el az ONNX webhelyére.
Az előre betanított Tiny YOLOv2 modell ONNX formátumban van tárolva, amely a rétegek és azok tanult mintáinak szerializált ábrázolása. A ML.NET az ONNX és a ImageAnalyticsOnnxTransformer NuGet csomagokkal való együttműködés érhető el. A ImageAnalytics csomag olyan átalakítások sorozatát tartalmazza, amelyek egy képet vesznek fel, és numerikus értékekre kódolják, amelyek az előrejelzési vagy betanítási folyamat bemeneteként használhatók. A OnnxTransformer csomag az ONNX runtime használatával tölt be egy ONNX-modellt, és a megadott bemenet alapján előrejelzéseket készít.
A .NET-konzolprojekt beállítása
Most, hogy általános ismereteket szerezhet az ONNX-ről és a Tiny YOLOv2 működéséről, ideje felépíteni az alkalmazást.
Konzolalkalmazás létrehozása
Hozzon létre egy "ObjectDetection" nevű C# -konzolalkalmazást . Kattintson a Tovább gombra.
Válassza a .NET 8-at a használni kívánt keretrendszerként. Kattintson a Létrehozás gombra.
Telepítse a Microsoft.ML NuGet-csomagot:
Megjegyzés:
Ez a minta az említett NuGet-csomagok legújabb stabil verzióját használja, hacsak másként nem rendelkezik.
- A Megoldáskezelőben kattintson a jobb gombbal a projektre, és válassza a NuGet-csomagok kezelése lehetőséget.
- Válassza a "nuget.org" lehetőséget csomagforrásként, válassza a Tallózás lapot, és keresse meg a Microsoft.ML.
- Válassza a Telepítés gombot.
- Kattintson az OK gombra a Változások előnézete párbeszédpanelen, majd válassza az Elfogadom gombot a Licenc elfogadása párbeszédpanelen, ha elfogadja a felsorolt csomagok licencfeltételét.
- Ismételje meg ezeket a lépéseket a Microsoft.Windows.Compatibility, a Microsoft.ML.ImageAnalytics, a Microsoft.ML.OnnxTransformer és a Microsoft.ML.OnnxRuntime esetében.
Az adatok és az előre betanított modell előkészítése
Töltse le a projekt assets könyvtár zip-fájlját és csomagolja ki.
Másolja a könyvtárat az
assetsObjectDetection projektkönyvtárába. Ez a könyvtár és alkönyvtárai tartalmazzák az oktatóanyaghoz szükséges képfájlokat (kivéve a Tiny YOLOv2 modellt, amelyet a következő lépésben letöltünk és hozzáadunk).Töltse le a Tiny YOLOv2 modellt az ONNX Model Zoo-ból.
Másolja a fájlt az
model.onnxObjectDetection projektkönyvtárábaassets\Model, és nevezze át a fájlraTinyYolo2_model.onnx. Ez a könyvtár az oktatóanyaghoz szükséges modellt tartalmazza.A Megoldáskezelőben kattintson a jobb gombbal az eszközkönyvtárban és az alkönyvtárakban lévő fájlokra, és válassza a Tulajdonságok lehetőséget. A Speciális területen módosítsa a Kimeneti könyvtárba másolás értékét Másolás, ha újabb.
Osztályok létrehozása és útvonalak definiálása
Nyissa meg a Program.cs fájlt, és adja hozzá a következő további using irányelveket a fájl tetejére:
using System.Drawing;
using System.Drawing.Drawing2D;
using ObjectDetection.YoloParser;
using ObjectDetection.DataStructures;
using ObjectDetection;
using Microsoft.ML;
Ezután határozza meg a különböző objektumok elérési útját.
Először hozza létre a metódust
GetAbsolutePatha Program.cs fájl alján.string GetAbsolutePath(string relativePath) { FileInfo _dataRoot = new FileInfo(typeof(Program).Assembly.Location); string assemblyFolderPath = _dataRoot.Directory.FullName; string fullPath = Path.Combine(assemblyFolderPath, relativePath); return fullPath; }Ezután az
usingirányelvek alatt hozzon létre mezőket az eszközök helyének tárolásához.var assetsRelativePath = @"../../../assets"; string assetsPath = GetAbsolutePath(assetsRelativePath); var modelFilePath = Path.Combine(assetsPath, "Model", "TinyYolo2_model.onnx"); var imagesFolder = Path.Combine(assetsPath, "images"); var outputFolder = Path.Combine(assetsPath, "images", "output");
Adjon hozzá egy új könyvtárat a projekthez a bemeneti adatok és előrejelzési osztályok tárolásához.
A Megoldáskezelőben kattintson a jobb gombbal a projektre, majd válassza azÚj mappa> lehetőséget. Amikor az új mappa megjelenik a Megoldáskezelőben, nevezze el "DataStructures"-nek.
Hozza létre a bemeneti adatosztályt az újonnan létrehozott DataStructures könyvtárban.
A Megoldáskezelőben kattintson a jobb gombbal a DataStructures könyvtárra, majd válassza azÚj elem> lehetőséget.
Az Új elem hozzáadása párbeszédpanelen válassza az Osztály lehetőséget, és módosítsa a Név mezőt ImageNetData.cs. Ezután válassza a Hozzáadás lehetőséget.
Megnyílik a ImageNetData.cs fájl a kódszerkesztőben. Adja hozzá a következő
usingirányelvet a ImageNetData.cs elejéhez:using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.ML.Data;Távolítsa el a meglévő osztálydefiníciót, és adja hozzá az
ImageNetDataosztály következő kódját a ImageNetData.cs fájlhoz:public class ImageNetData { [LoadColumn(0)] public string ImagePath; [LoadColumn(1)] public string Label; public static IEnumerable<ImageNetData> ReadFromFile(string imageFolder) { return Directory .GetFiles(imageFolder) .Where(filePath => Path.GetExtension(filePath) != ".md") .Select(filePath => new ImageNetData { ImagePath = filePath, Label = Path.GetFileName(filePath) }); } }ImageNetDataa bemeneti kép adatosztálya, és a következő String mezőket tartalmazza:-
ImagePatha rendszerkép tárolási útvonalát tartalmazza. -
Labela fájl nevét tartalmazza.
Emellett egy metódust
ImageNetDatais tartalmaz,ReadFromFileamely több, aimageFoldermegadott elérési úton tárolt képfájlt tölt be, és objektumgyűjteménykéntImageNetDataadja vissza őket.-
Hozza létre az előrejelzési osztályt a DataStructures könyvtárban.
A Megoldáskezelőben kattintson a jobb gombbal a DataStructures könyvtárra, majd válassza azÚj elem> lehetőséget.
Az Új elem hozzáadása párbeszédpanelen válassza az Osztály lehetőséget, és módosítsa a Név mezőt ImageNetPrediction.cs. Ezután válassza a Hozzáadás lehetőséget.
A ImageNetPrediction.cs fájl megnyílik a kódszerkesztőben. Adja hozzá a következő
usingirányelvet a ImageNetPrediction.cs elejéhez:using Microsoft.ML.Data;Távolítsa el a meglévő osztálydefiníciót, és adja hozzá az
ImageNetPredictionosztály következő kódját a ImageNetPrediction.cs fájlhoz:public class ImageNetPrediction { [ColumnName("grid")] public float[] PredictedLabels; }ImageNetPredictionaz előrejelzési adatosztály, és a következőfloat[]mezővel rendelkezik:-
PredictedLabelsa képen észlelt minden egyes határolókeret dimenzióit, objektumértékét és osztály valószínűségét tartalmazza.
-
Változók inicializálása
Az MLContext osztály minden ML.NET művelet kiindulópontja, és az inicializálás mlContext új ML.NET környezetet hoz létre, amely megosztható a modelllétrehozási munkafolyamat-objektumok között. Ez fogalmilag hasonló az Entity Frameworkhez DBContext .
Inicializálja a mlContext változót egy új példánysal MLContext úgy, hogy hozzáadja a következő sort a outputFolder mező alá.
MLContext mlContext = new MLContext();
Elemző létrehozása a folyamat utáni modellkimenetekhez
A modell egy képet egy 13 x 13 rácsba szegmentált, ahol az egyes rácscellák találhatók 32px x 32px. Minden rácscella 5 lehetséges objektum határolókeretet tartalmaz. A határolókeret 25 elemből áll:
-
xa határolókeret középpontjának x pozíciója a hozzá társított rácscellához viszonyítva. -
ya határolókeret középpontjának y pozíciója a hozzá társított rácscellához viszonyítva. -
wa határolókeret szélessége. -
ha határolókeret magassága. -
oaz objektumnak a határolókereten belüli megbízhatósági értéke, más néven objektumérték. -
p1-p20osztály-valószínűségek a modell által előrejelzett 20 osztály mindegyikéhez.
Összesen az 5 határolókeretet leíró 25 elem alkotja az egyes rácscellákban található 125 elemet.
Az előre betanított ONNX-modell által generált kimenet egy lebegőpontos hossztömb 21125, amely egy dimenziókkal 125 x 13 x 13rendelkező tenzor elemeit jelöli. Ahhoz, hogy a modell által generált előrejelzéseket tenzorlá alakíthassa, szükség van némi utófeldolgozási munkára. Ehhez hozzon létre egy osztálykészletet a kimenet elemzéséhez.
Adjon hozzá egy új könyvtárat a projekthez az elemzőosztályok halmazának rendszerezéséhez.
- A Megoldáskezelőben kattintson a jobb gombbal a projektre, majd válassza azÚj mappa> lehetőséget. Amikor megjelenik az új mappa a Megoldáskezelőben, nevezze el "YoloParser"-nek.
Határolókeretek és dimenziók létrehozása
A modell által megadott adatkimenet a képen belüli objektumok határolódobozainak koordinátáit és dimenzióit tartalmazza. Hozzon létre egy alaposztályt a dimenziókhoz.
A Megoldáskezelőben kattintson a jobb gombbal a YoloParser könyvtárra, majd válassza azÚj elem> lehetőséget.
Az Új elem hozzáadása párbeszédpanelen válassza az Osztály lehetőséget, és módosítsa a Név mezőt DimensionsBase.cs. Ezután válassza a Hozzáadás lehetőséget.
Megnyílik a DimensionsBase.cs fájl a kódszerkesztőben. Távolítsa el az összes
usingirányelvet és a meglévő osztálydefiníciót.Adja hozzá az
DimensionsBaseosztály következő kódját a DimensionsBase.cs fájlhoz:public class DimensionsBase { public float X { get; set; } public float Y { get; set; } public float Height { get; set; } public float Width { get; set; } }DimensionsBasea következőfloattulajdonságokkal rendelkezik:-
Xaz objektum pozícióját tartalmazza az x tengely mentén. -
Yaz objektum pozícióját tartalmazza az y tengely mentén. -
Heightaz objektum magasságát tartalmazza. -
Widthaz objektum szélességét tartalmazza.
-
Ezután hozzon létre egy osztályt a határolókeretekhez.
A Megoldáskezelőben kattintson a jobb gombbal a YoloParser könyvtárra, majd válassza azÚj elem> lehetőséget.
Az Új elem hozzáadása párbeszédpanelen válassza az Osztály lehetőséget, és módosítsa a Név mezőt YoloBoundingBox.cs. Ezután válassza a Hozzáadás lehetőséget.
A YoloBoundingBox.cs fájl megnyílik a kódszerkesztőben. Adja hozzá a következő
usingirányelvet a YoloBoundingBox.cs elejéhez:using System.Drawing;Az meglévő osztálydefiníció felett hozzon létre egy új,
BoundingBoxDimensionsnevű osztálydefiníciót, amely aDimensionsBaseosztályból öröklődik, hogy tartalmazza a megfelelő határolókeret méreteit.public class BoundingBoxDimensions : DimensionsBase { }Távolítsa el a meglévő
YoloBoundingBoxosztálydefiníciót, és adja hozzá azYoloBoundingBoxosztály következő kódját a YoloBoundingBox.cs fájlhoz:public class YoloBoundingBox { public BoundingBoxDimensions Dimensions { get; set; } public string Label { get; set; } public float Confidence { get; set; } public RectangleF Rect { get { return new RectangleF(Dimensions.X, Dimensions.Y, Dimensions.Width, Dimensions.Height); } } public Color BoxColor { get; set; } }YoloBoundingBoxa következő tulajdonságokkal rendelkezik:-
Dimensionsa határolókeret méreteit tartalmazza. -
LabelA határolókereten belül észlelt objektumosztályt tartalmazza. -
Confidenceaz osztály megbízhatóságát tartalmazza. -
Recta határolókeret méreteinek téglalapos ábrázolását tartalmazza. -
BoxColora kép rajzolásához használt megfelelő osztályhoz társított színt tartalmazza.
-
Az elemző létrehozása
Most, hogy létrejöttek a dimenziók és a határolókeretek osztályai, ideje létrehozni az elemzőt.
A Megoldáskezelőben kattintson a jobb gombbal a YoloParser könyvtárra, majd válassza azÚj elem> lehetőséget.
Az Új elem hozzáadása párbeszédpanelen válassza az Osztály lehetőséget, és módosítsa a Név mezőt YoloOutputParser.cs. Ezután válassza a Hozzáadás lehetőséget.
A YoloOutputParser.cs fájl megnyílik a kódszerkesztőben. Adja hozzá a következő
usingirányelveket a YoloOutputParser.cs elejéhez:using System; using System.Collections.Generic; using System.Drawing; using System.Linq;A meglévő
YoloOutputParserosztálydefiníción belül adjon hozzá egy beágyazott osztályt, amely a kép egyes celláinak dimenzióit tartalmazza. Adja hozzá a következő kódot azYoloOutputParserosztály definíciójának tetejére, amely egyDimensionsBaseosztályból örököltCellDimensionsosztályhoz tartozik.class CellDimensions : DimensionsBase { }YoloOutputParserAz osztálydefiníción belül adja hozzá a következő állandókat és mezőket.public const int ROW_COUNT = 13; public const int COL_COUNT = 13; public const int CHANNEL_COUNT = 125; public const int BOXES_PER_CELL = 5; public const int BOX_INFO_FEATURE_COUNT = 5; public const int CLASS_COUNT = 20; public const float CELL_WIDTH = 32; public const float CELL_HEIGHT = 32; private int channelStride = ROW_COUNT * COL_COUNT;-
ROW_COUNTa rács azon sorainak száma, amelyre a képet felosztották. -
COL_COUNTa rács oszlopainak száma, amelybe a rendszerkép fel van osztva. -
CHANNEL_COUNTA rács egy cellájában található értékek teljes száma. -
BOXES_PER_CELLaz egy cellában lévő határolókeretek száma, -
BOX_INFO_FEATURE_COUNTa mezőben található funkciók száma (x,y,magasság,szélesség,megbízhatóság). -
CLASS_COUNTaz egyes határolókeretekben található osztály-előrejelzések száma. -
CELL_WIDTHa képrács egy cellájának szélessége. -
CELL_HEIGHTa képrács egyik cellájának magassága. -
channelStrideaz aktuális cella kezdőpozíciója a rácsban.
Amikor a modell előrejelzést készít, más néven pontozást, a
416px x 416pxbemeneti képet egy olyan cellarácsra osztja, amelynek mérete13 x 13. Minden cella tartalmaz32px x 32px. Minden cellán belül 5 határolókeret található, amelyek mindegyike 5 funkciót tartalmaz (x, y, szélesség, magasság, megbízhatóság). Ezenkívül minden egyes határolókeret tartalmazza az osztályok valószínűségét, ami ebben az esetben 20. Ezért minden cella 125 információt tartalmaz (5 jellemző + 20 osztály valószínűsége).-
Hozzon létre egy listát az alábbi channelStride horgonyokról mind az 5 határolókerethez:
private float[] anchors = new float[]
{
1.08F, 1.19F, 3.42F, 4.41F, 6.63F, 11.38F, 9.42F, 5.11F, 16.62F, 10.52F
};
A horgonyok a határolókeretek előre meghatározott magassági és szélességi arányai. A modell által észlelt objektumok vagy osztályok többsége hasonló arányokkal rendelkezik. Ez különösen hasznos a határolókeretek létrehozásakor. A határolókeretek előrejelzése helyett az előre definiált dimenziók eltolását számítja ki a rendszer, így csökkenti a határolókeret előrejelzéséhez szükséges számítást. Ezek a horgonyarányok kiszámítása általában a használt adatkészlet alapján történik. Ebben az esetben, mivel az adathalmaz ismert, és az értékek előre lettek konfigurálva, a horgonyok kódoltak lehetnek.
Ezután adja meg a modell által előrejelzett címkéket vagy osztályokat. Ez a modell 20 osztályt jelez előre, amely az eredeti YOLOv2 modell által előrejelzett osztályok teljes számának részhalmaza.
Adja hozzá a címkék listáját a következő alá: anchors.
private string[] labels = new string[]
{
"aeroplane", "bicycle", "bird", "boat", "bottle",
"bus", "car", "cat", "chair", "cow",
"diningtable", "dog", "horse", "motorbike", "person",
"pottedplant", "sheep", "sofa", "train", "tvmonitor"
};
Mindegyik osztályhoz vannak színek társítva. Rendelje hozzá az osztályszíneket a következőhöz labels:
private static Color[] classColors = new Color[]
{
Color.Khaki,
Color.Fuchsia,
Color.Silver,
Color.RoyalBlue,
Color.Green,
Color.DarkOrange,
Color.Purple,
Color.Gold,
Color.Red,
Color.Aquamarine,
Color.Lime,
Color.AliceBlue,
Color.Sienna,
Color.Orchid,
Color.Tan,
Color.LightPink,
Color.Yellow,
Color.HotPink,
Color.OliveDrab,
Color.SandyBrown,
Color.DarkTurquoise
};
Segédfüggvények létrehozása
Az utófeldolgozási fázisban több lépés is szerepel. Ennek érdekében számos segítő módszert lehet alkalmazni.
Az elemző által használt segédmetódusok a következők:
-
Sigmoida szigmoid függvényt alkalmazza, amely 0 és 1 közötti számot ad ki. -
Softmaxa bemeneti vektort valószínűségeloszlássá normalizálja. -
GetOffsetaz egydimenziós modell kimenetének elemeit a tenzorban lévő megfelelő pozíciókra125 x 13 x 13képezi le. -
ExtractBoundingBoxesa modell kimenetéből kinyeri a határolókeret dimenzióit aGetOffsetmetódus használatával. -
GetConfidenceKinyeri a megbízhatósági értéket, amely azt jelzi, hogy a modell mennyire biztos abban, hogy észlelt egy objektumot, és aSigmoidfüggvény használatával százalékot ad. -
MapBoundingBoxToCella határolókeret méreteit használja, és a kép megfelelő cellájára vetíti rá őket. -
ExtractClasseskinyeri a határolókeret osztály-előrejelzéseit a modell kimenetéből aGetOffsetmetódus használatával, és aSoftmaxmetódus segítségével valószínűségeloszlássá alakítja őket. -
GetTopResultA legnagyobb valószínűséggel rendelkező előrejelzett osztályok listájából választja ki az osztályt. -
IntersectionOverUnionkisebb valószínűségű, átfedésben lévő határolókereteket szűr.
Adja hozzá a kódot az összes segítő metódushoz a lista classColorsalatt.
private float Sigmoid(float value)
{
var k = (float)Math.Exp(value);
return k / (1.0f + k);
}
private float[] Softmax(float[] values)
{
var maxVal = values.Max();
var exp = values.Select(v => Math.Exp(v - maxVal));
var sumExp = exp.Sum();
return exp.Select(v => (float)(v / sumExp)).ToArray();
}
private int GetOffset(int x, int y, int channel)
{
// YOLO outputs a tensor that has a shape of 125x13x13, which
// WinML flattens into a 1D array. To access a specific channel
// for a given (x,y) cell position, we need to calculate an offset
// into the array
return (channel * this.channelStride) + (y * COL_COUNT) + x;
}
private BoundingBoxDimensions ExtractBoundingBoxDimensions(float[] modelOutput, int x, int y, int channel)
{
return new BoundingBoxDimensions
{
X = modelOutput[GetOffset(x, y, channel)],
Y = modelOutput[GetOffset(x, y, channel + 1)],
Width = modelOutput[GetOffset(x, y, channel + 2)],
Height = modelOutput[GetOffset(x, y, channel + 3)]
};
}
private float GetConfidence(float[] modelOutput, int x, int y, int channel)
{
return Sigmoid(modelOutput[GetOffset(x, y, channel + 4)]);
}
private CellDimensions MapBoundingBoxToCell(int x, int y, int box, BoundingBoxDimensions boxDimensions)
{
return new CellDimensions
{
X = ((float)x + Sigmoid(boxDimensions.X)) * CELL_WIDTH,
Y = ((float)y + Sigmoid(boxDimensions.Y)) * CELL_HEIGHT,
Width = (float)Math.Exp(boxDimensions.Width) * CELL_WIDTH * anchors[box * 2],
Height = (float)Math.Exp(boxDimensions.Height) * CELL_HEIGHT * anchors[box * 2 + 1],
};
}
public float[] ExtractClasses(float[] modelOutput, int x, int y, int channel)
{
float[] predictedClasses = new float[CLASS_COUNT];
int predictedClassOffset = channel + BOX_INFO_FEATURE_COUNT;
for (int predictedClass = 0; predictedClass < CLASS_COUNT; predictedClass++)
{
predictedClasses[predictedClass] = modelOutput[GetOffset(x, y, predictedClass + predictedClassOffset)];
}
return Softmax(predictedClasses);
}
private ValueTuple<int, float> GetTopResult(float[] predictedClasses)
{
return predictedClasses
.Select((predictedClass, index) => (Index: index, Value: predictedClass))
.OrderByDescending(result => result.Value)
.First();
}
private float IntersectionOverUnion(RectangleF boundingBoxA, RectangleF boundingBoxB)
{
var areaA = boundingBoxA.Width * boundingBoxA.Height;
if (areaA <= 0)
return 0;
var areaB = boundingBoxB.Width * boundingBoxB.Height;
if (areaB <= 0)
return 0;
var minX = Math.Max(boundingBoxA.Left, boundingBoxB.Left);
var minY = Math.Max(boundingBoxA.Top, boundingBoxB.Top);
var maxX = Math.Min(boundingBoxA.Right, boundingBoxB.Right);
var maxY = Math.Min(boundingBoxA.Bottom, boundingBoxB.Bottom);
var intersectionArea = Math.Max(maxY - minY, 0) * Math.Max(maxX - minX, 0);
return intersectionArea / (areaA + areaB - intersectionArea);
}
Miután definiálta az összes segédmetó módszert, ideje őket használni a modell kimenetének feldolgozásához.
IntersectionOverUnion A metódus alatt hozza létre a metódust a ParseOutputs modell által létrehozott kimenet feldolgozásához.
public IList<YoloBoundingBox> ParseOutputs(float[] yoloModelOutputs, float threshold = .3F)
{
}
Hozzon létre egy listát a határolókeretek tárolásához és a ParseOutputs változók metóduson belüli definiálásához.
var boxes = new List<YoloBoundingBox>();
Minden kép cellarácsra 13 x 13 van osztva. Minden cella öt darab határolókeretet tartalmaz.
boxes A változó alatt adjon hozzá kódot az egyes cellák összes dobozának feldolgozásához.
for (int row = 0; row < ROW_COUNT; row++)
{
for (int column = 0; column < COL_COUNT; column++)
{
for (int box = 0; box < BOXES_PER_CELL; box++)
{
}
}
}
A legbelső hurokban számítsa ki az aktuális mező kezdőpozícióját az egydimenziós modell kimenetén belül.
var channel = (box * (CLASS_COUNT + BOX_INFO_FEATURE_COUNT));
Közvetlenül alatta, használja a ExtractBoundingBoxDimensions metódust az aktuális határolókeret méreteinek lekéréséhez.
BoundingBoxDimensions boundingBoxDimensions = ExtractBoundingBoxDimensions(yoloModelOutputs, row, column, channel);
Ezután használja a metódust GetConfidence az aktuális határolókeret megbízhatóságának lekéréséhez.
float confidence = GetConfidence(yoloModelOutputs, row, column, channel);
Ezt követően a MapBoundingBoxToCell metódussal megfelelteti az aktuális határolókeretet a feldolgozandó aktuális cellának.
CellDimensions mappedBoundingBox = MapBoundingBoxToCell(row, column, box, boundingBoxDimensions);
A további feldolgozás előtt ellenőrizze, hogy a megbízhatósági érték nagyobb-e a megadott küszöbértéknél. Ha nem, dolgozza fel a következő határolókeretet.
if (confidence < threshold)
continue;
Ellenkező esetben folytassa a kimenet feldolgozását. A következő lépés az, hogy a ExtractClasses módszer használatával megkapjuk az aktuális határolókeret előrejelzett osztályainak valószínűségeloszlását.
float[] predictedClasses = ExtractClasses(yoloModelOutputs, row, column, channel);
Ezután a GetTopResult metódussal lekérheti annak az osztálynak az értékét és indexét, amelynek legnagyobb a valószínűsége az aktuális mezőben, és kiszámítja a pontszámát.
var (topResultIndex, topResultScore) = GetTopResult(predictedClasses);
var topScore = topResultScore * confidence;
Ezzel ismét csak azokat a topScore határolókereteket tartsa meg, amelyek túllépik a megadott küszöbértéket.
if (topScore < threshold)
continue;
Végül, ha az aktuális határolókeret túllépi a küszöbértéket, hozzon létre egy új BoundingBox objektumot, és adja hozzá a boxes listához.
boxes.Add(new YoloBoundingBox()
{
Dimensions = new BoundingBoxDimensions
{
X = (mappedBoundingBox.X - mappedBoundingBox.Width / 2),
Y = (mappedBoundingBox.Y - mappedBoundingBox.Height / 2),
Width = mappedBoundingBox.Width,
Height = mappedBoundingBox.Height,
},
Confidence = topScore,
Label = labels[topResultIndex],
BoxColor = classColors[topResultIndex]
});
A kép összes cellájának feldolgozása után adja vissza a boxes listát. Adja hozzá a következő visszatérési utasítást a metódusban a legkülönlegesebb for-loop ParseOutputs alá.
return boxes;
Átfedésben lévő mezők szűrése
Most, hogy az összes nagyon magabiztos határolókeret ki lett nyerve a modell kimenetéből, további szűrést kell végezni az átfedésben lévő képek eltávolításához. Adjon hozzá egy metódus alatti metódust FilterBoundingBoxesParseOutputs :
public IList<YoloBoundingBox> FilterBoundingBoxes(IList<YoloBoundingBox> boxes, int limit, float threshold)
{
}
A metóduson FilterBoundingBoxes belül először hozzon létre egy olyan tömböt, amely megegyezik az észlelt dobozok méretével, és az összes tárolóhelyet aktívként vagy feldolgozásra készként jelöli meg.
var activeCount = boxes.Count;
var isActiveBoxes = new bool[boxes.Count];
for (int i = 0; i < isActiveBoxes.Length; i++)
isActiveBoxes[i] = true;
Ezután rendezze a határolókereteket tartalmazó listát csökkenő sorrendbe a megbízhatóság alapján.
var sortedBoxes = boxes.Select((b, i) => new { Box = b, Index = i })
.OrderByDescending(b => b.Box.Confidence)
.ToList();
Ezután hozzon létre egy listát a szűrt eredmények tárolásához.
var results = new List<YoloBoundingBox>();
Kezdje el feldolgozni az egyes határolókereteket úgy, hogy iterál rajtuk.
for (int i = 0; i < boxes.Count; i++)
{
}
Ebben a for-loopban ellenőrizze, hogy az aktuális határolókeret feldolgozható-e.
if (isActiveBoxes[i])
{
}
Ha igen, adja hozzá a határolókeretet az eredmények listájához. Ha az eredmények túllépik a kinyerni kívánt mezők megadott korlátját, bontsa ki a hurkot. Adja hozzá a következő kódot az if-utasításban.
var boxA = sortedBoxes[i].Box;
results.Add(boxA);
if (results.Count >= limit)
break;
Ellenkező esetben nézze meg a szomszédos határolókereteket. Adja hozzá a következő kódot a jelölőnégyzetkorlát alá.
for (var j = i + 1; j < boxes.Count; j++)
{
}
Az első mezőhöz hasonlóan, ha a szomszédos mező aktív vagy készen áll a feldolgozásra, a IntersectionOverUnion módszerrel ellenőrizheti, hogy az első és a második mező túllépi-e a megadott küszöbértéket. Adja hozzá a következő kódot a legbelső for-loophoz.
if (isActiveBoxes[j])
{
var boxB = sortedBoxes[j].Box;
if (IntersectionOverUnion(boxA.Rect, boxB.Rect) > threshold)
{
isActiveBoxes[j] = false;
activeCount--;
if (activeCount <= 0)
break;
}
}
A szomszédos határolókereteket ellenőrző legbelső for-hurokon kívül ellenőrizze, hogy vannak-e még feldolgozandó határolókeretek. Ha nem, bontsa ki a külső for-loop.
if (activeCount <= 0)
break;
Végül a metódus kezdeti for-loopon FilterBoundingBoxes kívül adja vissza az eredményeket:
return results;
Nagyszerű! Most itt az ideje, hogy ezt a kódot a pontozási modellel együtt használja.
A modell használata pontozáshoz
Az utófeldolgozáshoz hasonlóan a pontozási lépésekben is van néhány lépés. Ehhez adjon hozzá egy osztályt, amely tartalmazza a pontozási logikát a projektben.
A Megoldáskezelőben kattintson a jobb gombbal a projektre, majd válassza azÚj elem>.
Az Új elem hozzáadása párbeszédpanelen válassza az Osztály lehetőséget, és módosítsa a Név mezőt OnnxModelScorer.cs. Ezután válassza a Hozzáadás lehetőséget.
Megnyílik a OnnxModelScorer.cs fájl a kódszerkesztőben. Adja hozzá a következő
usingirányelveket a OnnxModelScorer.cs elejéhez:using System; using System.Collections.Generic; using System.Linq; using Microsoft.ML; using Microsoft.ML.Data; using ObjectDetection.DataStructures; using ObjectDetection.YoloParser;OnnxModelScorerAz osztálydefiníción belül adja hozzá a következő változókat.private readonly string imagesFolder; private readonly string modelLocation; private readonly MLContext mlContext; private IList<YoloBoundingBox> _boundingBoxes = new List<YoloBoundingBox>();Közvetlenül alatta hozzon létre egy konstruktort az
OnnxModelScorerosztályhoz, amely inicializálja a korábban definiált változókat.public OnnxModelScorer(string imagesFolder, string modelLocation, MLContext mlContext) { this.imagesFolder = imagesFolder; this.modelLocation = modelLocation; this.mlContext = mlContext; }Miután létrehozta a konstruktort, definiáljon néhány szerkezetet, amelyek a rendszerképhez és a modell beállításaihoz kapcsolódó változókat tartalmaznak. Hozzon létre egy szerkezetet
ImageNetSettings, amely a modell bemeneteként várt magasságot és szélességet tartalmazza.public struct ImageNetSettings { public const int imageHeight = 416; public const int imageWidth = 416; }Ezután hozzon létre egy másik, a
TinyYoloModelSettingsmodell bemeneti és kimeneti rétegeinek nevét tartalmazó szerkezetet. A modell bemeneti és kimeneti rétegeinek nevének megjelenítéséhez használhat egy olyan eszközt, mint a Netron.public struct TinyYoloModelSettings { // for checking Tiny yolo2 Model input and output parameter names, //you can use tools like Netron, // which is installed by Visual Studio AI Tools // input tensor name public const string ModelInput = "image"; // output tensor name public const string ModelOutput = "grid"; }Ezután hozza létre a pontozáshoz használt módszerek első készletét. Hozza létre a metódust
LoadModelazOnnxModelScorerosztályon belül.private ITransformer LoadModel(string modelLocation) { }A metóduson
LoadModelbelül adja hozzá a következő kódot a naplózáshoz.Console.WriteLine("Read model"); Console.WriteLine($"Model location: {modelLocation}"); Console.WriteLine($"Default parameters: image size=({ImageNetSettings.imageWidth},{ImageNetSettings.imageHeight})");ML.NET folyamatoknak ismernie kell a metódus meghívásakor
Fitműködő adatsémát. Ebben az esetben a rendszer a betanításhoz hasonló folyamatot használ. Mivel azonban nem történik tényleges betanítás, elfogadhatóIDataViewüres . Hozzon létre egy újatIDataViewa folyamathoz egy üres listából.var data = mlContext.Data.LoadFromEnumerable(new List<ImageNetData>());Alatta definiálja a folyamatot. A folyamat négy átalakításból áll.
-
LoadImagesbetölti a képet bitképként. -
ResizeImagesa rendszerképet a megadott méretre (ebben az esetben416 x 416) skálázhatja újra. -
ExtractPixelsbitképről numerikus vektorra módosítja a kép képpontos ábrázolását. -
ApplyOnnxModelbetölti az ONNX-modellt, és a megadott adatok pontszámára használja.
Definiálja a folyamatot a
LoadModelváltozó alattidatametódusban.var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "image", imageFolder: "", 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: modelLocation, outputColumnNames: new[] { TinyYoloModelSettings.ModelOutput }, inputColumnNames: new[] { TinyYoloModelSettings.ModelInput }));Itt az ideje, hogy példányosítsuk a modellt a pontozáshoz. Hívja meg a metódust
Fita folyamaton, és adja vissza további feldolgozás céljából.var model = pipeline.Fit(data); return model;-
Miután betöltötte a modellt, az előrejelzések készítésére is használható. A folyamat megkönnyítése érdekében hozzon létre egy metódust PredictDataUsingModel a LoadModel metódus alatt.
private IEnumerable<float[]> PredictDataUsingModel(IDataView testData, ITransformer model)
{
}
Adja hozzá a PredictDataUsingModelkövetkező kódot a naplózáshoz.
Console.WriteLine($"Images location: {imagesFolder}");
Console.WriteLine("");
Console.WriteLine("=====Identify the objects in the images=====");
Console.WriteLine("");
Ezután használja a metódust Transform az adatok pontozására.
IDataView scoredData = model.Transform(testData);
Nyerje ki az előrejelzett valószínűségeket, és adja vissza őket további feldolgozás céljából.
IEnumerable<float[]> probabilities = scoredData.GetColumn<float[]>(TinyYoloModelSettings.ModelOutput);
return probabilities;
Most, hogy mindkét lépés be van állítva, kombinálja őket egyetlen módszerrel.
PredictDataUsingModel A metódus alatt adjon hozzá egy új, úgynevezett metódustScore.
public IEnumerable<float[]> Score(IDataView data)
{
var model = LoadModel(modelLocation);
return PredictDataUsingModel(data, model);
}
Majdnem ott! Most itt az ideje, hogy mindent használni.
Objektumok észlelése
Most, hogy az összes beállítás befejeződött, ideje észlelni néhány objektumot.
Modellkimenetek pontszáma és elemzése
A változó létrehozása mlContext alatt adjon hozzá egy try-catch utasítást.
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
A blokkon try belül kezdje el implementálni az objektumészlelési logikát. Először töltse be az adatokat egy IDataView.
IEnumerable<ImageNetData> images = ImageNetData.ReadFromFile(imagesFolder);
IDataView imageDataView = mlContext.Data.LoadFromEnumerable(images);
Ezután hozzon létre egy példányt OnnxModelScorer , és használja a betöltött adatok pontozásához.
// Create instance of model scorer
var modelScorer = new OnnxModelScorer(imagesFolder, modelFilePath, mlContext);
// Use model to score data
IEnumerable<float[]> probabilities = modelScorer.Score(imageDataView);
Itt az idő az utófeldolgozási lépésre. Hozzon létre egy példányt YoloOutputParser , és használja a modell kimenetének feldolgozásához.
YoloOutputParser parser = new YoloOutputParser();
var boundingBoxes =
probabilities
.Select(probability => parser.ParseOutputs(probability))
.Select(boxes => parser.FilterBoundingBoxes(boxes, 5, .5F));
A modellkimenet feldolgozása után ideje megrajzolni a határolókereteket a képeken.
Előrejelzések megjelenítése
Miután a modell pontozza a képeket, és a kimenetek feldolgozásra kerültek, a határolókereteket a képre kell rajzolni. Ehhez adjon hozzá egy metódust DrawBoundingBox a metódus alatt, GetAbsolutePath Program.cs belül.
void DrawBoundingBox(string inputImageLocation, string outputImageLocation, string imageName, IList<YoloBoundingBox> filteredBoundingBoxes)
{
}
Először töltse be a képet, és kérje le a magassági és szélességi méreteket a DrawBoundingBox metódusban.
Image image = Image.FromFile(Path.Combine(inputImageLocation, imageName));
var originalImageHeight = image.Height;
var originalImageWidth = image.Width;
Ezután hozzon létre egy for-each hurkot, hogy végigmenjen a modell által észlelt összes határolókereten.
foreach (var box in filteredBoundingBoxes)
{
}
A for-each cikluson belül szerezze be a határolódoboz méreteit.
var x = (uint)Math.Max(box.Dimensions.X, 0);
var y = (uint)Math.Max(box.Dimensions.Y, 0);
var width = (uint)Math.Min(originalImageWidth - x, box.Dimensions.Width);
var height = (uint)Math.Min(originalImageHeight - y, box.Dimensions.Height);
Mivel a határolókeret méretei megfelelnek a modell bemenetének 416 x 416, skálázza a határolókeret méreteit a kép tényleges méretének megfelelően.
x = (uint)originalImageWidth * x / OnnxModelScorer.ImageNetSettings.imageWidth;
y = (uint)originalImageHeight * y / OnnxModelScorer.ImageNetSettings.imageHeight;
width = (uint)originalImageWidth * width / OnnxModelScorer.ImageNetSettings.imageWidth;
height = (uint)originalImageHeight * height / OnnxModelScorer.ImageNetSettings.imageHeight;
Ezután definiáljon egy sablont az egyes határolókeretek fölött megjelenő szöveghez. A szöveg tartalmazza az objektum osztályát a megfelelő határolókereten belül, valamint a megbízhatóságot.
string text = $"{box.Label} ({(box.Confidence * 100).ToString("0")}%)";
A kép rajzolásához konvertálja objektummá Graphics .
using (Graphics thumbnailGraphic = Graphics.FromImage(image))
{
}
using A kódblokkon belül hangolja be a grafikus Graphics objektum beállításait.
thumbnailGraphic.CompositingQuality = CompositingQuality.HighQuality;
thumbnailGraphic.SmoothingMode = SmoothingMode.HighQuality;
thumbnailGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
Alatta adja meg a szöveg és a határolókeret betűtípus- és színbeállítását.
// Define Text Options
Font drawFont = new Font("Arial", 12, FontStyle.Bold);
SizeF size = thumbnailGraphic.MeasureString(text, drawFont);
SolidBrush fontBrush = new SolidBrush(Color.Black);
Point atPoint = new Point((int)x, (int)y - (int)size.Height - 1);
// Define BoundingBox options
Pen pen = new Pen(box.BoxColor, 3.2f);
SolidBrush colorBrush = new SolidBrush(box.BoxColor);
Hozzon létre és töltsön ki egy téglalapot a határolókeret felett a szöveg elhelyezéséhez a FillRectangle metódus használatával. Ez segít a szöveg kontrasztosabbá tételében és az olvashatóság javításában.
thumbnailGraphic.FillRectangle(colorBrush, (int)x, (int)(y - size.Height - 1), (int)size.Width, (int)size.Height);
Ezután rajzolja meg a szöveget és a határolókeretet a képen a DrawString és a DrawRectangle metódusok használatával.
thumbnailGraphic.DrawString(text, drawFont, fontBrush, atPoint);
// Draw bounding box on image
thumbnailGraphic.DrawRectangle(pen, x, y, width, height);
Az elemenkénti cikluson kívül adjon hozzá kódot a képek mentéséhez a outputFolder.
if (!Directory.Exists(outputImageLocation))
{
Directory.CreateDirectory(outputImageLocation);
}
image.Save(Path.Combine(outputImageLocation, imageName));
Ha további visszajelzést szeretne arról, hogy az alkalmazás futásidőben a vártnak megfelelően előrejelzéseket készít, adjon hozzá egy metódus alatti LogDetectedObjects metódust DrawBoundingBox a Program.cs fájlban az észlelt objektumok konzolon való kimenetéhez.
void LogDetectedObjects(string imageName, IList<YoloBoundingBox> boundingBoxes)
{
Console.WriteLine($".....The objects in the image {imageName} are detected as below....");
foreach (var box in boundingBoxes)
{
Console.WriteLine($"{box.Label} and its Confidence score: {box.Confidence}");
}
Console.WriteLine("");
}
Most, hogy már rendelkezik segítő módszerekkel az előrejelzésekből származó vizuális visszajelzések létrehozásához, adjon hozzá egy for ciklust, hogy iteráljon az egyes értékelt képeken.
for (var i = 0; i < images.Count(); i++)
{
}
A for-loopon belül kérje le a képfájl nevét és a hozzá tartozó határolókereteket.
string imageFileName = images.ElementAt(i).Label;
IList<YoloBoundingBox> detectedObjects = boundingBoxes.ElementAt(i);
Ez alatt a DrawBoundingBox módszerrel rajzolhatja meg a határolókereteket a képen.
DrawBoundingBox(imagesFolder, outputFolder, imageFileName, detectedObjects);
Végül a LogDetectedObjects metódus használatával előrejelzéseket ad ki a konzolnak.
LogDetectedObjects(imageFileName, detectedObjects);
A try-catch utasítás után adjon hozzá további logikát a folyamat futásának jelzéséhez.
Console.WriteLine("========= End of Process..Hit any Key ========");
Ennyi az egész!
Results
Az előző lépések végrehajtása után futtassa a konzolalkalmazást (Ctrl + F5). Az eredményeknek az alábbi kimenethez hasonlónak kell lenniük. Megjelenhetnek figyelmeztetések vagy feldolgozással kapcsolatos üzenetek, de ezeket az üzeneteket eltávolítottuk az alábbi eredményekből az egyértelműség érdekében.
=====Identify the objects in the images=====
.....The objects in the image image1.jpg are detected as below....
car and its Confidence score: 0.9697262
car and its Confidence score: 0.6674225
person and its Confidence score: 0.5226039
car and its Confidence score: 0.5224892
car and its Confidence score: 0.4675332
.....The objects in the image image2.jpg are detected as below....
cat and its Confidence score: 0.6461141
cat and its Confidence score: 0.6400049
.....The objects in the image image3.jpg are detected as below....
chair and its Confidence score: 0.840578
chair and its Confidence score: 0.796363
diningtable and its Confidence score: 0.6056048
diningtable and its Confidence score: 0.3737402
.....The objects in the image image4.jpg are detected as below....
dog and its Confidence score: 0.7608147
person and its Confidence score: 0.6321323
dog and its Confidence score: 0.5967442
person and its Confidence score: 0.5730394
person and its Confidence score: 0.5551759
========= End of Process..Hit any Key ========
Ha határolókereteket tartalmazó képeket szeretne látni, navigáljon a assets/images/output/ könyvtárba. Az alábbiakban egy minta látható az egyik feldolgozott rendszerképből.
Gratulálok! Sikeresen létrehozott egy gépi tanulási modellt az objektumészleléshez egy előre betanított ONNX modell az ML.NET-ben való újrahasználatával.
Az oktatóanyag forráskódját a dotnet/machinelearning-samples adattárban találja.
Ez az oktatóanyag bemutatta, hogyan végezheti el az alábbi műveleteket:
- A probléma ismertetése
- Ismerje meg, mi az ONNX, és hogyan működik ML.NET
- A modell megismerése
- Az előre betanított modell újrafelhasználása
- Betöltött modellel rendelkező objektumok észlelése
A bővített objektumészlelési minta megismeréséhez tekintse meg a Machine Learning-minták GitHub-adattárát.