Öğretici: ML.NET'te ONNX kullanarak nesneleri algılama
görüntülerdeki nesneleri algılamak için ML.NET'te önceden eğitilmiş bir ONNX modelini kullanmayı öğrenin.
Sıfırdan nesne algılama modeli eğitirken milyonlarca parametre, çok miktarda etiketlenmiş eğitim verisi ve çok büyük miktarda işlem kaynağı (yüzlerce GPU saati) ayarlanması gerekir. Önceden eğitilmiş bir model kullanmak, eğitim sürecinin kısayolunu oluşturmana olanak sağlar.
Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:
- Sorunu anlama
- ONNX'in ne olduğunu ve ML.NET ile nasıl çalıştığını öğrenin
- Modeli anlama
- Önceden eğitilmiş modeli yeniden kullanma
- Yüklenen modele sahip nesneleri algılama
Ön koşullar
- Visual Studio 2022 .
- Microsoft. ML NuGet Paketi
- Microsoft. ML. ImageAnalytics NuGet Paketi
- Microsoft. ML. OnnxTransformer NuGet Paketi
- Küçük YOLOv2 önceden eğitilmiş model
- Netron (isteğe bağlı)
ONNX nesne algılama örneğine genel bakış
Bu örnek, önceden eğitilmiş bir derin öğrenme ONNX modelini kullanarak bir görüntüdeki nesneleri algılayan bir .NET Core konsol uygulaması oluşturur. Bu örneğin kodu, GitHub'da dotnet/machinelearning-samples deposunda bulunabilir.
Nesne algılama nedir?
Nesne algılama bir görüntü oluşturma sorunudur. Nesne algılama, görüntü sınıflandırması ile yakından ilgiliyken görüntü sınıflandırmayı daha ayrıntılı bir ölçekte gerçekleştirir. Nesne algılama, görüntüler içindeki varlıkları bulup kategorilere ayırıyor. Nesne algılama modelleri genellikle derin öğrenme ve sinir ağları kullanılarak eğitilmiş olur. Daha fazla bilgi için bkz. Derin öğrenme ve makine öğrenmesi.
Görüntüler farklı türlerde birden çok nesne içerdiği zaman nesne algılamayı kullanın.

Nesne algılama için bazı kullanım örnekleri şunlardır:
- Self-Driving Cars
- Robotik
- Yüz Algılama
- İş Yeri Güvenliği
- Nesne Sayma
- Etkinlik Tanıma
Derin öğrenme modeli seçme
Derin öğrenme, makine öğrenmesinin bir alt kümesidir. Derin öğrenme modellerini eğitmek için büyük miktarlarda veri gerekir. Verilerde desenler bir dizi katmanla temsil edildi. Verilerde yer alan ilişkiler, ağırlık içeren katmanlar arasında bağlantı olarak kodlanmış. Ağırlık ne kadar yüksek ise ilişki o kadar güçlü olur. Bu katman ve bağlantı serisi topluca yapay sinir ağları olarak bilinir. Bir ağ içinde ne kadar çok katman oluşursa o kadar derin bir sinir ağı olur.
En yaygın olan Çok Katmanlı Perceptron (MLP), Konvolutional Sinir Ağı (CNN) ve Özyinelemeli Sinir Ağı (RNN) olan farklı sinir ağı türleri vardır. En basiti, bir giriş kümesiyle çıkış kümesi eşleyeni MLP'dir. Bu sinir ağı, verilerin uzamsal veya zaman bileşenine sahip olmadığını gösterir. CNN, verilerde yer alan uzamsal bilgileri işlemeye ilişkin konvolutsal katmanları kullanır. CNN'ler için iyi bir kullanım örneği, görüntünün bir bölgesinde bir özelliğin varlığını algılamak için görüntü işlemedir (örneğin, görüntünün merkezinde bir burun var mı?). Son olarak, RNN'ler giriş olarak kullanılacak durum veya bellek kalıcılığı sağlar. RNN'ler sıralı sıralamanın ve olayların bağlamının önemli olduğu zaman serisi analizi için kullanılır.
Modeli anlama
Nesne algılama bir görüntü işleme görevidir. Bu nedenle, bu sorunu çözmek için eğitilen derin öğrenme modellerinin çoğu, CNN'lerdir. Bu öğreticide kullanılan model, YOLOv2 modelinin daha küçük bir sürümü olan Vezir ve Farhadi tarafından "YOLO9000: Better, Faster, Stronger" (YolO9000: Better, Faster, Stronger)makalesinde açıklanan küçük YOLOv2 modelidir. Küçük YOLOv2, Pascal VOC veri kümesi üzerinde eğitilmiş ve 20 farklı nesne sınıflarını tahmin edile 15 katmandan oluşur. Tiny YOLOv2, özgün YOLOv2 modelinin yoğun bir sürümü olduğundan hız ve doğruluk arasında bir takas yapılır. Modelin farklı katmanları, Netron gibi araçlar kullanılarak görselleştirilebilirsiniz. Modeli incelerken sinir ağına göre tüm katmanlar arasındaki bağlantıların eşlemesi elde edersiniz. Burada her katmanda ilgili giriş/çıkış boyutlarıyla birlikte katmanın adı yer alır. Modelin giriş ve çıkışlarını açıklamak için kullanılan veri yapıları tensors olarak bilinir. Tensörler, verileri N boyutlu olarak depolana kapsayıcılar olarak düşünebilirsiniz. Tiny YOLOv2 durumunda giriş katmanının adı olur ve image tensor boyut 3 x 416 x 416 bekler. Çıkış katmanının adıdır grid ve boyutlardan bir çıkış tensor'ları 125 x 13 x 13 oluşturur.

YOLO modeli bir görüntü 3(RGB) x 416px x 416px alır. Model bu girişi alır ve çıkış üretmek için farklı katmanlardan geçer. Çıkış, giriş görüntüsünü bir kılavuza 13 x 13 böler ve kılavuzda her hücre değerlerden 125 oluşur.
ONNX modeli nedir?
Açık Sinir Ağı Exchange (ONNX), yapay zeka modelleri için açık kaynak bir biçimdir. ONNX çerçeveler arasında birlikte çalışabilirliği destekler. Bu, PyTorch gibi popüler makine öğrenmesi çerçevelerinden biri ile modeli eğitip ONNX biçimine dönüştürerek onNX modelini ML.NET gibi farklı bir çerçevede tüketebilirsiniz. Daha fazla bilgi edinmek için ONNX web sitesini ziyaret edin.

Önceden eğitilmiş Küçük YOLOv2 modeli, katmanların serileştirilmiş bir gösterimi ve bu katmanların öğrenilen desenleri olan ONNX biçiminde depolanır. ML.NET'te ONNX ile birlikte çalışabilirlik, ve NuGet ImageAnalytics OnnxTransformer sağlanır. Paket, bir görüntüyü alıp tahmin veya eğitim işlem hattına giriş olarak kullanılan sayısal değerlere kodlayan ImageAnalytics bir dizi dönüştürme içerir. Paket, onNX modelini yüklemek için ONNX Çalışma Zamanı'nın kullanır ve sağlanan OnnxTransformer girişe dayalı tahminler yapmak için bu modeli kullanır.

.NET Konsol projesini ayarlama
ARTıK ONNX'in ne olduğunu ve Tiny YOLOv2'nin nasıl çalıştığını genel olarak anlabilirsiniz. Şimdi uygulamayı derlemenin zamanı geldi.
Konsol uygulaması oluşturma
"ObjectDetection" adlı bir C# Konsol Uygulaması oluşturun. Sonraki düğmesine tıklayın.
Çerçeve olarak .NET 6'yi seçin. Oluştur düğmesine tıklayın.
Microsoft.ML'i yükleme NuGet Paketi:
Not
Bu örnek, aksi belirtilmediği takdirde, belirtilen NuGet paketlerinin en son kararlı sürümünü kullanır.
- Bu Çözüm Gezgini projenize sağ tıklayın ve Paketleri Yönet'NuGet seçin.
- Paket nuget.org"ı seçin, Gözat sekmesini seçin ve Microsoft.ML.
- Yükle düğmesini seçin.
- Listelenen paketler için lisans koşullarını kabul ediyorsanız, Değişiklikleri Önizle iletişim kutusunda Tamam düğmesini ve ardından Lisans Kabulü iletişim kutusundaki Kabul Ediyorum düğmesini seçin.
- Bu adımları Microsoft.ML. ImageAnalytics, Microsoft.ML. OnnxTransformer ve Microsoft.ML. OnnxRuntime.
Verilerinizi ve önceden eğitilmiş modelinizi hazırlama
Proje varlıkları dizin zip dosyasını indirin ve sıkıştırmayı açın.
Dizini
assetsObjectDetection proje dizininize kopyalayın. Bu dizin ve onun alt dizinleri, bu öğretici için gereken görüntü dosyalarını (bir sonraki adımda indirip ekleyazın Tiny YOLOv2 modeli dışında) içerir.Küçük YOLOv2 modelini ONNX Model Zoo'dan indirin.
Dosyayı
model.onnxObjectDetection proje dizininize kopyalayınassets\Modelve olarak yenidenTinyYolo2_model.onnxadlandırabilirsiniz. Bu dizin, bu öğretici için gereken modeli içerir.Bu Çözüm Gezgini, varlık dizininde ve alt dizinlerde bulunan dosyaların her biri için sağ tıklayın ve Özellikler'i seçin. Gelişmiş' in altında, Çıkış Dizinine Kopyala değerini daha yeniyse kopyala olarak değiştirin.
Sınıf oluşturma ve yollar tanımlama
Program. cs dosyasını açın ve aşağıdaki ek using deyimlerini dosyanın en üstüne ekleyin:
using System;
using System.IO;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Microsoft.ML;
Ardından, çeşitli varlıkların yollarını tanımlayın.
İlk olarak,
GetAbsolutePathprogram. cs dosyasının en altında yöntemi oluşturun.public static 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; }Ardından, using deyimlerinin altında varlıklarınızın konumunu depolamak için alanlar oluşturun.
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");
Giriş verilerinizi ve tahmin sınıflarınızı depolamak için projenize yeni bir dizin ekleyin.
Çözüm Gezgini, projeye sağ tıklayın ve ardından > Yeni klasör Ekle ' yi seçin. Yeni klasör Çözüm Gezgini göründüğünde, "Datayapýlarý" olarak adlandırın.
Yeni oluşturulan Datayapýlarý dizininde giriş veri sınıfınızı oluşturun.
Çözüm Gezgini, datayapýlarý dizinine sağ tıklayıp > Yeni öğe Ekle ' yi seçin.
Yeni öğe Ekle Iletişim kutusunda sınıf ' ı seçin ve ad alanını ımagenetdata. cs olarak değiştirin. Sonra Ekle düğmesini seçin.
Imagenetdata. cs dosyası kod düzenleyicisinde açılır. Aşağıdaki
usingIfadeyi Imagenetdata. cs' nin üst kısmına ekleyin:using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.ML.Data;Mevcut sınıf tanımını kaldırın ve sınıf için aşağıdaki kodu
ImageNetDataımagenetdata. cs dosyasına ekleyin: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) }); } }ImageNetData, giriş resmi veri sınıfıdır ve aşağıdaki String alanlara sahiptir:ImagePathgörüntünün depolandığı yolu içerir.Labeldosyanın adını içerir.
Ayrıca,
ImageNetDataReadFromFilebelirtilen yolda depolanan birden çok resim dosyasını yükleyenimageFolderve bunları bir nesne koleksiyonu olarak döndüren bir yöntemi içerirImageNetData.
Veri yapıları dizininde tahmin sınıfınızı oluşturun.
Çözüm Gezgini, datayapýlarý dizinine sağ tıklayıp > Yeni öğe Ekle ' yi seçin.
Yeni öğe Ekle Iletişim kutusunda sınıf ' ı seçin ve ad alanını ımagenettahmine. cs olarak değiştirin. Sonra Ekle düğmesini seçin.
Imagenettahminini. cs dosyası kod düzenleyicisinde açılır. Aşağıdaki
usingIfadeyi ımagenettahmine. cs' nin üst kısmına ekleyin:using Microsoft.ML.Data;Mevcut sınıf tanımını kaldırın ve sınıf için aşağıdaki kodu
ImageNetPredictionımagenettahmine. cs dosyasına ekleyin:public class ImageNetPrediction { [ColumnName("grid")] public float[] PredictedLabels; }ImageNetPrediction, tahmin verileri sınıfıdır ve şufloat[]alana sahiptir:PredictedLabelgörüntüde algılanan her bir sınırlayıcı kutu için boyutları, objectlik Puanını ve sınıf olasılıkları içerir.
Değişkenleri Başlat
mlcontext sınıfı tüm ML .net işlemleri için bir başlangıç noktasıdır ve başlatma işlemi, mlContext model oluşturma iş akışı nesneleri genelinde paylaşılabilen yeni bir ML .net ortamı oluşturur. Entity Framework, kavramsal olarak da benzerdir DBContext .
mlContext MLContext Alanının altına aşağıdaki satırı ekleyerek değişkeni yeni bir örneğiyle başlatın outputFolder .
MLContext mlContext = new MLContext();
İşlem sonrası model çıkışları için bir Ayrıştırıcı oluşturun
Model, 13 x 13 her kılavuz hücresinin bulunduğu bir görüntüyü kılavuza böler 32px x 32px . Her kılavuz hücresi, 5 olası nesne sınırlayıcı kutusu içerir. Bir sınırlayıcı kutusunda 25 öğe vardır:

xsınırlama kutusu merkezinin ilişkilendirildiği kılavuz hücresine göre x konumu.ysınırlama kutusu merkezinin ilişkilendirildiği kılavuz hücresine göre y konumu.wsınırlayıcı kutunun genişliği.hsınırlayıcı kutunun yüksekliği.obir nesnenin, sınırlayıcı kutusunda bulunduğu güven değeri, aynı zamanda objectlik puanı olarak da bilinir.p1-p20model tarafından tahmin edilen 20 sınıfın her biri için sınıf olasılıkların.
Toplamda, 5 sınırlayıcı kutulardan her birini tanımlayan 25 öğe, her kılavuz hücresinde bulunan 125 öğelerini yapar.
Önceden eğitilen ONNX modeli tarafından oluşturulan çıkış, 21125 boyutlarla birlikte bir ön sor öğelerinin öğelerini temsil eden bir float dizisidir 125 x 13 x 13 . Model tarafından oluşturulan tahminleri bir tencursor 'a dönüştürmek için bazı işleme sonrası işler gereklidir. Bunu yapmak için, çıktıyı ayrıştırmaya yardımcı olmak üzere bir sınıf kümesi oluşturun.
Ayrıştırıcı sınıfları kümesini düzenlemek için projenize yeni bir dizin ekleyin.
- Çözüm Gezgini, projeye sağ tıklayın ve ardından > Yeni klasör Ekle ' yi seçin. Yeni klasör Çözüm Gezgini göründüğünde, "YoloParser" olarak adlandırın.
Sınırlayıcı kutular ve boyutlar oluşturma
Modelin veri çıktısı, görüntü içindeki nesnelerin sınırlayıcı kutularının koordinatlarını ve boyutlarını içerir. Boyutlar için bir temel sınıf oluşturun.
Çözüm Gezgini, yoloparser dizinine sağ tıklayın ve sonra > Yeni öğe Ekle ' yi seçin.
Yeni öğe Ekle Iletişim kutusunda sınıf ' ı seçin ve ad alanını dimensionsbase. cs olarak değiştirin. Sonra Ekle düğmesini seçin.
Dimensionsbase. cs dosyası kod düzenleyicisinde açılır. Tüm
usingdeyimlerini ve varolan sınıf tanımını kaldırın.Sınıfı için aşağıdaki kodu
DimensionsBaseDimensionsbase. cs dosyasına ekleyin:public class DimensionsBase { public float X { get; set; } public float Y { get; set; } public float Height { get; set; } public float Width { get; set; } }DimensionsBaseaşağıdaki özelliklere sahiptirfloat:Xnesnenin x ekseni üzerindeki konumunu içerir.Ynesnenin y ekseni üzerinde konumunu içerir.Heightnesnenin yüksekliğini içerir.Widthnesnenin genişliğini içerir.
Ardından, sınırlayıcı kutularınız için bir sınıf oluşturun.
Çözüm Gezgini, yoloparser dizinine sağ tıklayın ve sonra > Yeni öğe Ekle ' yi seçin.
Yeni öğe Ekle Iletişim kutusunda sınıf ' ı seçin ve ad alanını yoloboundingbox. cs olarak değiştirin. Sonra Ekle düğmesini seçin.
Yoloboundingbox. cs dosyası kod düzenleyicisinde açılır. Aşağıdaki
usingIfadeyi Yoloboundingbox. cs' nin üst kısmına ekleyin:using System.Drawing;Mevcut sınıf tanımının hemen üzerinde,
BoundingBoxDimensionsDimensionsBaseilgili sınırlayıcı kutusunun boyutlarını içerecek şekilde sınıfından devralan adlı yeni bir sınıf tanımı ekleyin.public class BoundingBoxDimensions : DimensionsBase { }Mevcut
YoloBoundingBoxsınıf tanımını kaldırın ve sınıf için aşağıdaki koduYoloBoundingBoxYoloboundingbox. cs dosyasına ekleyin: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şağıdaki özelliklere sahiptir:Dimensionssınırlayıcı kutunun boyutlarını içerir.Labelsınırlayıcı kutusunda algılanan nesne sınıfını içerir.Confidencesınıfının güvenini içerir.Rectsınırlayıcı kutunun boyutlarının dikdörtgen gösterimini içerir.BoxColorgörüntüde çizim yapmak için kullanılan ilgili sınıfla ilişkili rengi içerir.
Ayrıştırıcı oluşturma
Artık boyut ve sınırlama kutuları için sınıflar oluşturuldığına göre, ayrıştırıcısı oluşturma zamanı.
Çözüm Gezgini, yoloparser dizinine sağ tıklayın ve sonra > Yeni öğe Ekle ' yi seçin.
Yeni öğe Ekle Iletişim kutusunda sınıf ' ı seçin ve ad alanını yolooutputparser. cs olarak değiştirin. Sonra Ekle düğmesini seçin.
Yolooutputparser. cs dosyası kod düzenleyicisinde açılır. Aşağıdaki
usingIfadeyi Yolooutputparser. cs' nin üst kısmına ekleyin:using System; using System.Collections.Generic; using System.Drawing; using System.Linq;Varolan
YoloOutputParsersınıf tanımının içinde, görüntüdeki her bir hücrenin boyutlarını içeren bir iç içe sınıf ekleyin. SınıfCellDimensionsDimensionsBasetanımının en üstündeki sınıftan devralan sınıf için aşağıdaki kodu ekleyinYoloOutputParser.class CellDimensions : DimensionsBase { }YoloOutputParserSınıf tanımı içinde, aşağıdaki sabitleri ve alanları ekleyin.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_COUNT, görüntüdeki görüntünün bölüneceğini, ızgaradaki satır sayısıdır.COL_COUNT, görüntüde bölünen, kılavuzdaki sütun sayısıdır.CHANNEL_COUNTkılavuzun tek bir hücresinde bulunan toplam değer sayısıdır.BOXES_PER_CELL, bir hücredeki sınırlayıcı kutuların sayısıdır,BOX_INFO_FEATURE_COUNT, bir kutu içinde (x, y, Height, Width, güvenirlik) bulunan özelliklerin sayısıdır.CLASS_COUNT, her bir sınırlayıcı kutusunda bulunan sınıf tahminleri sayısıdır.CELL_WIDTH, görüntü kılavuzundaki bir hücrenin genişliğidir.CELL_HEIGHT, görüntü kılavuzundaki bir hücrenin yüksekliğidir.channelStrideKılavuzdaki geçerli hücrenin başlangıç konumudur.
Model, Puanlama olarak da bilinen bir tahmin yaptığında,
416px x 416pxgiriş görüntüsünü boyutunun bir hücre kılavuzuna böler13 x 13. Her hücre içerir32px x 32px. Her hücrede, 5 Özellik (x, y, Width, Height, güvenirlik) içeren 5 sınırlayıcı kutu vardır. Bunlara ek olarak, her bir sınırlayıcı kutu her bir sınıfın olasılığını içerir, bu durumda 20 olur. Bu nedenle, her hücre 125 bilgi parçasını içerir (5 özellik + 20 sınıf olasılıkların).
Tüm 5 sınırlayıcı kutular için aşağıdan bir çıpası listesi oluşturun channelStride :
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
};
Bağlayıcıların sınırlayıcı kutuların önceden tanımlanmış yükseklik ve genişlik oranları vardır. Bir model tarafından algılanan çoğu nesne veya sınıfın benzer oranları vardır. Bu, sınırlayıcı kutular oluşturmak için kullanışlıdır. Sınırlayıcı kutuları tahmin etmek yerine, önceden tanımlanmış boyutlardan olan fark, bu nedenle, sınırlayıcı kutuyu tahmin etmek için gereken hesaplamayı azaltmak için hesaplanır. Genellikle bu bağlantı oranları, kullanılan veri kümesi temel alınarak hesaplanır. Bu durumda, veri kümesi bilindiği ve değerler önceden hesaplandığından, bağlantılar sabit kodlanmış olabilir.
Ardından, modelin tahmin edecek etiketleri veya sınıfları tanımlayın. Bu model, özgün YOLOv2 modeli tarafından tahmin edilen toplam sınıf sayısının bir alt kümesi olan 20 sınıfı tahmin eder.
Altına etiket listenizi ekleyin 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"
};
Sınıfların her biriyle ilişkili renkler vardır. Sınıf renklerinizi aşağıdaki gibi atayın 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
};
Yardımcı işlevler oluşturma
İşleme sonrası aşamasında yer alan bir dizi adım vardır. Bu konuda yardımcı olmak için birkaç yardımcı yöntem kullanılabilir.
Ayrıştırıcı tarafından kullanılan yardımcı yöntemler şunlardır:
Sigmoid0 ile 1 arasında bir sayı çıkışı yapan sigmoıd işlevini uygular.Softmaxbir giriş vektörünü bir olasılık dağıtımına normalleştirir.GetOffsettek boyutlu model çıkışındaki öğeleri bir tencursor içindeki ilgili konuma eşler125 x 13 x 13.ExtractBoundingBoxesModel çıktısından yöntemi kullanarak sınırlama kutusu boyutlarını ayıklarGetOffset.GetConfidencemodelin bir nesne algıladığı veSigmoidbunu bir yüzdeye dönüştürmek için işlevini kullandığı emin olan güvenirlik değerini ayıklar.MapBoundingBoxToCell, sınırlayıcı kutu boyutlarını kullanır ve bunları görüntünün içindeki ilgili hücresiyle eşler.ExtractClassesyöntemi kullanarak model çıktısından sınırlama kutusu için sınıf tahminlerini ayıklarGetOffsetve yöntemi kullanarak bunları bir olasılık dağıtımına dönüştürürSoftmax.GetTopResulten yüksek olasılığa sahip tahmin edilen sınıflar listesinden sınıfı seçer.IntersectionOverUniondaha düşük olasılıklara sahip sınırlayıcı kutuları filtreler.
Listenizin altındaki tüm yardımcı yöntemleri için kodu ekleyin classColors .
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);
}
Tüm yardımcı yöntemlerini tanımladıktan sonra, model çıkışını işlemek için bunları kullanma zamanı da vardır.
Yönteminin altında IntersectionOverUnion , ParseOutputs model tarafından oluşturulan çıktıyı işlemek için yöntemi oluşturun.
public IList<YoloBoundingBox> ParseOutputs(float[] yoloModelOutputs, float threshold = .3F)
{
}
Sınırlayıcı kutularınızı depolamak ve yöntemin içinde değişkenleri tanımlamak için bir liste oluşturun ParseOutputs .
var boxes = new List<YoloBoundingBox>();
Her resim bir hücre kılavuzuna bölünmüştür 13 x 13 . Her hücrede beş sınırlayıcı kutu bulunur. Değişkenin altında boxes , her hücrenin içindeki tüm kutuları işlemek için kod ekleyin.
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++)
{
}
}
}
En içteki döngünün içinde, tek boyutlu model çıkışı içindeki geçerli kutunun başlangıç konumunu hesaplayın.
var channel = (box * (CLASS_COUNT + BOX_INFO_FEATURE_COUNT));
Doğrudan altında, ExtractBoundingBoxDimensions geçerli sınırlayıcı kutusunun boyutlarını almak için yöntemini kullanın.
BoundingBoxDimensions boundingBoxDimensions = ExtractBoundingBoxDimensions(yoloModelOutputs, row, column, channel);
Ardından, GetConfidence geçerli sınırlayıcı kutusunun güvenini almak için yöntemini kullanın.
float confidence = GetConfidence(yoloModelOutputs, row, column, channel);
Bundan sonra, MapBoundingBoxToCell geçerli sınırlayıcı kutuyu işlenmekte olan geçerli hücreyle eşlemek için yöntemini kullanın.
CellDimensions mappedBoundingBox = MapBoundingBoxToCell(row, column, box, boundingBoxDimensions);
Daha fazla işlem yapmadan önce, güven değerinin sağlanan eşikten büyük olup olmadığını kontrol edin. Aksi takdirde, sonraki sınırlayıcı kutuyu işleyin.
if (confidence < threshold)
continue;
Aksi takdirde, çıktıyı işlemeye devam edin. Sonraki adımda, yöntemi kullanılarak geçerli sınırlayıcı kutu için öngörülen sınıfların olasılık dağılımı alınır ExtractClasses .
float[] predictedClasses = ExtractClasses(yoloModelOutputs, row, column, channel);
Daha sonra, GetTopResult Geçerli kutu için en yüksek olasılığa sahip sınıfın değerini ve dizinini almak ve Puanını hesaplamak için yöntemini kullanın.
var (topResultIndex, topResultScore) = GetTopResult(predictedClasses);
var topScore = topResultScore * confidence;
' İ topScore bir kez daha kullanarak yalnızca belirtilen eşiğin üzerinde olan sınırlayıcı kutuları saklayın.
if (topScore < threshold)
continue;
Son olarak, geçerli sınırlayıcı kutusu eşiği aşarsa, yeni bir BoundingBox nesne oluşturun ve boxes listeye ekleyin.
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]
});
Görüntüdeki tüm hücreler işlendikten sonra listeyi geri döndürün boxes . Aşağıdaki return ifadesini yöntemine en dıştaki for-Loop altına ekleyin ParseOutputs .
return boxes;
Çakışan kutuları filtrele
Artık yüksek oranda uygun sınırlama kutularının tümü model çıktısından ayıklandığına göre, çakışan görüntüleri kaldırmak için ek filtrelemenin yapılması gerekir. Yönteminin altına adlı bir yöntem ekleyin FilterBoundingBoxes ParseOutputs :
public IList<YoloBoundingBox> FilterBoundingBoxes(IList<YoloBoundingBox> boxes, int limit, float threshold)
{
}
Yöntemi içinde FilterBoundingBoxes , algılanan kutuların boyutuna eşit bir dizi oluşturarak ve tüm yuvaları etkin veya işleme hazırmış olarak işaretleyerek devre dışı bırakın.
var activeCount = boxes.Count;
var isActiveBoxes = new bool[boxes.Count];
for (int i = 0; i < isActiveBoxes.Length; i++)
isActiveBoxes[i] = true;
Ardından, sınırlayıcı kutularınızı içeren listeyi güvenle azalan sırada sıralayın.
var sortedBoxes = boxes.Select((b, i) => new { Box = b, Index = i })
.OrderByDescending(b => b.Box.Confidence)
.ToList();
Bundan sonra filtrelenmiş sonuçları tutacak bir liste oluşturun.
var results = new List<YoloBoundingBox>();
Her bir sınırlayıcı kutunun her biri üzerinde yinelenerek her bir sınırlayıcı kutuyu işlemeye başlayın.
for (int i = 0; i < boxes.Count; i++)
{
}
Bu for-döngüsünün içinde, geçerli sınırlayıcı kutusunun işlenip işlenemeyeceğini kontrol edin.
if (isActiveBoxes[i])
{
}
Bu durumda, sınırlama kutusunu sonuçlar listesine ekleyin. Sonuçlar Ayıklanacak belirlenen kutu sınırını aşarsa döngüyü sonlandırın. Aşağıdaki kodu if-deyimin içine ekleyin.
var boxA = sortedBoxes[i].Box;
results.Add(boxA);
if (results.Count >= limit)
break;
Aksi takdirde, bitişik sınırlayıcı kutulara bakın. Aşağıdaki kodu Box limit denetiminin altına ekleyin.
for (var j = i + 1; j < boxes.Count; j++)
{
}
İlk kutu gibi, bitişik kutu etkin veya işlenmek üzere hazırsanız, IntersectionOverUnion ilk kutunun ve ikinci kutunun belirtilen eşiği aşıp aşmadığını denetlemek için yöntemini kullanın. Aşağıdaki kodu en içteki for-loop ' a ekleyin.
if (isActiveBoxes[j])
{
var boxB = sortedBoxes[j].Box;
if (IntersectionOverUnion(boxA.Rect, boxB.Rect) > threshold)
{
isActiveBoxes[j] = false;
activeCount--;
if (activeCount <= 0)
break;
}
}
Bitişik sınırlayıcı kutuları denetleyen en büyük for-Loop dışında, işlenmek üzere kalan herhangi bir sınırlama kutusu olup olmadığına bakın. Aksi takdirde, için dış döngüden çıkar.
if (activeCount <= 0)
break;
Son olarak, yöntemin ilk döngüsü dışında, FilterBoundingBoxes sonuçları döndürün:
return results;
Harika! Artık bu kodu Puanlama modeliyle birlikte kullanmanın zamanı.
Puanlama için modeli kullanma
İşlem sonrasında olduğu gibi, Puanlama adımlarında birkaç adım vardır. Bu konuda yardım almak için, projenize Puanlama mantığını içerecek bir sınıf ekleyin.
Çözüm Gezgini, projeye sağ tıklayın ve ardından > Yeni öğe Ekle ' yi seçin.
Yeni öğe Ekle Iletişim kutusunda sınıf ' ı seçin ve ad alanını OnnxModelScorer. cs olarak değiştirin. Sonra Ekle düğmesini seçin.
OnnxModelScorer. cs dosyası kod düzenleyicisinde açılır. Aşağıdaki
usingIfadeyi OnnxModelScorer. cs' nin en üstüne ekleyin:using System; using System.Collections.Generic; using System.Linq; using Microsoft.ML; using Microsoft.ML.Data; using ObjectDetection.DataStructures; using ObjectDetection.YoloParser;OnnxModelScorerSınıf tanımı içinde aşağıdaki değişkenleri ekleyin.private readonly string imagesFolder; private readonly string modelLocation; private readonly MLContext mlContext; private IList<YoloBoundingBox> _boundingBoxes = new List<YoloBoundingBox>();Doğrudan altında,
OnnxModelScorerdaha önce tanımlanmış değişkenleri başlatacak sınıf için bir Oluşturucu oluşturun.public OnnxModelScorer(string imagesFolder, string modelLocation, MLContext mlContext) { this.imagesFolder = imagesFolder; this.modelLocation = modelLocation; this.mlContext = mlContext; }Oluşturucuyu oluşturduktan sonra, görüntü ve model ayarlarıyla ilgili değişkenleri içeren birkaç yapı tanımlayın.
ImageNetSettingsModel için girdi olarak beklenen yüksekliği ve genişliği içeren bir struct oluşturun.public struct ImageNetSettings { public const int imageHeight = 416; public const int imageWidth = 416; }Bundan sonra,
TinyYoloModelSettingsmodelin giriş ve çıkış katmanlarının adlarını içeren adlı başka bir struct oluşturun. Modelin giriş ve çıkış katmanlarının adını görselleştirmek için, netrongibi bir araç kullanabilirsiniz.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"; }Ardından, Puanlama için kullanılan ilk yöntem kümesini oluşturun.
LoadModelSınıfınızın içindeki yöntemi oluşturunOnnxModelScorer.private ITransformer LoadModel(string modelLocation) { }Yöntemi içinde
LoadModelgünlüğe kaydetmek için aşağıdaki kodu ekleyin.Console.WriteLine("Read model"); Console.WriteLine($"Model location: {modelLocation}"); Console.WriteLine($"Default parameters: image size=({ImageNetSettings.imageWidth},{ImageNetSettings.imageHeight})");ML .net işlem hatları, yöntemi çağrıldığında üzerinde çalışılacak veri şemasını bilmelidir
Fit. Bu durumda, eğitimle benzer bir süreç kullanılacaktır. Ancak, hiçbir gerçek eğitim gerçekleşmediğinden boş kullanılması kabul edilebilirIDataView.IDataViewBoş bir listeden işlem hattı için yeni bir oluştur.var data = mlContext.Data.LoadFromEnumerable(new List<ImageNetData>());Bunun altında, işlem hattını tanımlayın. İşlem hattı dört dönüşümden oluşur.
LoadImagesgörüntüyü bir bit eşlem olarak yükler.ResizeImagesgörüntüyü belirtilen boyuta ölçeklendirin (Bu durumda,416 x 416).ExtractPixelsgörüntünün piksel temsilini bir bit eşlemden sayısal bir Vector öğesine değiştirir.ApplyOnnxModelONNX modelini yükler ve belirtilen verileri öğrenmek için onu kullanır.
İşlem hattınızı
LoadModeldeğişkenin altındaki yöntemde tanımlayındata.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 }));Şimdi Puanlama için model oluşturma zamanı. İşlem hattında
Fityöntemi çağırın ve daha fazla işleme için döndürün.var model = pipeline.Fit(data); return model;
Model yüklendikten sonra tahmin yapmak için kullanılabilir. Bu işlemi kolaylaştırmak için yönteminin altında adlı bir yöntem oluşturun PredictDataUsingModel LoadModel .
private IEnumerable<float[]> PredictDataUsingModel(IDataView testData, ITransformer model)
{
}
içine, PredictDataUsingModel günlüğe kaydetme için aşağıdaki kodu ekleyin.
Console.WriteLine($"Images location: {imagesFolder}");
Console.WriteLine("");
Console.WriteLine("=====Identify the objects in the images=====");
Console.WriteLine("");
Ardından, verileri Transform puan almak için yöntemini kullanın.
IDataView scoredData = model.Transform(testData);
Tahmin edilen olasılıkları ayıklar ve ek işleme için bunları geri döner.
IEnumerable<float[]> probabilities = scoredData.GetColumn<float[]>(TinyYoloModelSettings.ModelOutput);
return probabilities;
Artık her iki adım da ayarnan, bunları tek bir yöntemde birleştirin. yönteminin PredictDataUsingModel altına adlı yeni bir yöntem Score ekleyin.
public IEnumerable<float[]> Score(IDataView data)
{
var model = LoadModel(modelLocation);
return PredictDataUsingModel(data, model);
}
Neredeyse bitti! Şimdi hepsini kullanmak üzere koyabilirsiniz.
Nesneleri algılama
Tüm kurulum tamamlandıktan sonra bazı nesneleri algılamanın zamanı geldi. Program.cs sınıfınıza puanleyici ve ayrıştırıcıya başvurular ekleyerek başlayabilirsiniz.
using ObjectDetection.YoloParser;
using ObjectDetection.DataStructures;
Model çıkışlarını puanla ve ayrıştır
değişkeninin oluşturulmasının mlContext altına bir try-catch deyimi ekleyin.
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Bloğun try içinde nesne algılama mantığını uygulamaya başlama. İlk olarak, verileri bir içine IDataView yükleme.
IEnumerable<ImageNetData> images = ImageNetData.ReadFromFile(imagesFolder);
IDataView imageDataView = mlContext.Data.LoadFromEnumerable(images);
Ardından, bir örneği oluşturun OnnxModelScorer ve yüklenen verileri puan almak için bunu kullanın.
var modelScorer = new OnnxModelScorer(imagesFolder, modelFilePath, mlContext);
// Use model to score data
IEnumerable<float[]> probabilities = modelScorer.Score(imageDataView);
Artık işleme sonrası adımının zamanı geldi. bir örneği oluşturun YoloOutputParser ve modelin çıkışını işlemek için bunu kullanın.
YoloOutputParser parser = new YoloOutputParser();
var boundingBoxes =
probabilities
.Select(probability => parser.ParseOutputs(probability))
.Select(boxes => parser.FilterBoundingBoxes(boxes, 5, .5F));
Model çıkışı işlendikten sonra görüntülere sınırlayıcı kutuları çizmenin zamanı geldi.
Tahminleri görselleştirme
Model görüntüleri puanlamanın ardından ve çıkışlar işlendikten sonra sınırlayıcı kutuların görüntü üzerinde çiziliyor olması gerekir. Bunu yapmak için DrawBoundingBox GetAbsolutePath Program.cs içindeki yönteminin altına adlı bir yöntem ekleyin.
void DrawBoundingBox(string inputImageLocation, string outputImageLocation, string imageName, IList<YoloBoundingBox> filteredBoundingBoxes)
{
}
İlk olarak, görüntüyü yükp yönteminde yükseklik ve genişlik boyutlarını DrawBoundingBox elde edersiniz.
Image image = Image.FromFile(Path.Combine(inputImageLocation, imageName));
var originalImageHeight = image.Height;
var originalImageWidth = image.Width;
Ardından, model tarafından algılanan sınırlayıcı kutuların her biri üzerinde yinelene bir for-each döngüsü oluşturun.
foreach (var box in filteredBoundingBoxes)
{
}
for-each döngüsünde sınırlayıcı kutunun boyutlarını elde edin.
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);
Sınırlayıcı kutunun boyutları model girişine karşılık gelen olduğundan, sınırlayıcı kutu boyutlarını görüntünün gerçek boyutuyla 416 x 416 eş olacak şekilde ölçeklendirin.
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;
Ardından, her sınırlayıcı kutunun üzerinde görünecek metin için bir şablon tanımlayın. Metin, ilgili sınırlayıcı kutunun içindeki nesnenin sınıfını ve güveni içerir.
string text = $"{box.Label} ({(box.Confidence * 100).ToString("0")}%)";
Görüntüyü çizmek için bir nesnesine Graphics dönüştürebilirsiniz.
using (Graphics thumbnailGraphic = Graphics.FromImage(image))
{
}
Kod using bloğunda grafiğin nesne ayarlarını Graphics yapın.
thumbnailGraphic.CompositingQuality = CompositingQuality.HighQuality;
thumbnailGraphic.SmoothingMode = SmoothingMode.HighQuality;
thumbnailGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
Bunun altında, metin ve sınırlayıcı kutu için yazı tipi ve renk seçeneklerini ayarlayın.
// 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);
yöntemini kullanarak metni içermesi için sınırlayıcı kutunun üzerinde bir dikdörtgen oluşturun ve FillRectangle doldurun. Bu, metnin karşıtlığı ve okunabilirliği artırmaya yardımcı olur.
thumbnailGraphic.FillRectangle(colorBrush, (int)x, (int)(y - size.Height - 1), (int)size.Width, (int)size.Height);
Ardından, ve yöntemlerini kullanarak görüntüde metin ve sınırlayıcı DrawString kutuyu DrawRectangle çizin.
thumbnailGraphic.DrawString(text, drawFont, fontBrush, atPoint);
// Draw bounding box on image
thumbnailGraphic.DrawRectangle(pen, x, y, width, height);
for-each döngüsü dışında, görüntüleri içinde kaydetmek için kod outputDirectory ekleyin.
if (!Directory.Exists(outputImageLocation))
{
Directory.CreateDirectory(outputImageLocation);
}
image.Save(Path.Combine(outputImageLocation, imageName));
Uygulamanın çalışma zamanında beklendiği gibi tahminlerde bulunarak ilgili ek geri bildirim için LogDetectedObjects DrawBoundingBox Program.cs dosyasında yönteminin altına adlı bir yöntem ekerek algılanan nesneleri konsola çıkış olarak ekleyin.
private static 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("");
}
Tahminlerden görsel geri bildirim oluşturmak için yardımcı yöntemlere sahip olduğunuza göre, puanlı görüntülerin her birini tekrar etmek için bir for-loop ekleyin.
for (var i = 0; i < images.Count(); i++)
{
}
for-loop içinde görüntü dosyasının adını ve ilişkili sınırlayıcı kutuları bulun.
string imageFileName = images.ElementAt(i).Label;
IList<YoloBoundingBox> detectedObjects = boundingBoxes.ElementAt(i);
Bunun altında, DrawBoundingBox görüntüye sınırlayıcı kutuları çizmek için yöntemini kullanın.
DrawBoundingBox(imagesFolder, outputFolder, imageFileName, detectedObjects);
Son olarak, LogDetectedObjects konsola tahmin çıkışı yapmak için yöntemini kullanın.
LogDetectedObjects(imageFileName, detectedObjects);
try-catch deyiminden sonra, işlemi çalıştırmanın tamam olduğunu belirtmek için ek mantık ekleyin.
Console.WriteLine("========= End of Process..Hit any Key ========");
Console.ReadLine();
İşte bu kadar!
Sonuçlar
Önceki adımları takip edin ve konsol uygulamalarınızı çalıştırın (Ctrl + F5). Sonuçlarınız aşağıdaki çıkışa benzer olabilir. Uyarılar veya işleme iletileri görebilir, ancak bu iletiler netlik sağlamak için aşağıdaki sonuçlardan kaldırılmıştır.
=====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 ========
Sınırlayıcı kutulara sahip görüntüleri görmek için dizinine assets/images/output/ gidin. Aşağıda, işlenen görüntülerden bir örnek verilmiştir.

Tebrikler! ML.NET'te önceden eğitilmiş bir modeli yeniden kullanarak nesne algılama için başarıyla bir makine öğrenmesi modeli ONNX ML.
Bu öğreticinin kaynak kodunu dotnet/machinelearning-samples deposunda bulabilirsiniz.
Bu öğreticide, şunların nasıl yapıldığını öğrendiniz:
- Sorunu anlama
- ONNX'in ne olduğunu ve ML.NET ile nasıl çalıştığını öğrenin
- Modeli anlama
- Önceden eğitilmiş modeli yeniden kullanma
- Yüklenen modele sahip nesneleri algılama
Genişletilmiş nesne algılama Machine Learning keşfetmek için GitHub örnek örneklerine göz atabilirsiniz.