Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
görüntülerdeki nesneleri algılamak için ML.NET'de önceden eğitilmiş bir ONNX modelini kullanmayı öğrenin.
Sıfırdan nesne algılama modelini eğitme, milyonlarca parametre, büyük miktarda etiketlenmiş eğitim verisi ve çok miktarda işlem kaynağı (yüzlerce GPU saati) ayarlamayı gerektirir. Önceden eğitilmiş bir model kullanmak, eğitim sürecine kısayol oluşturmanıza olanak tanır.
Bu öğreticide aşağıdakilerin nasıl yapılacağı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üklü bir modelle nesneleri algılama
Önkoşullar
- Visual Studio 2022.
- NuGet Paketini Microsoft.ML
- 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 modeli kullanarak görüntüdeki nesneleri algılayan bir .NET core konsol uygulaması oluşturur. Bu örneğin kodu GitHub'daki dotnet/machinelearning-samples deposunda bulunabilir.
Nesne algılama nedir?
Nesne algılama bir görüntü işleme sorunudur. Nesne algılama, görüntü sınıflandırmasıyla yakından ilişkili olsa da görüntü sınıflandırmasını daha ayrıntılı bir ölçekte gerçekleştirir. Nesne algılama, görüntüler içindeki varlıkları hem bulur hem de kategorilere ayırır. Nesne algılama modelleri genellikle derin öğrenme ve sinir ağları kullanılarak eğitilir. Daha fazla bilgi için bkz . Derin öğrenme ve makine öğrenmesi .
Görüntüler farklı türde birden çok nesne içerdiğinde nesne algılamayı kullanın.

Nesne algılama için bazı kullanım örnekleri şunlardır:
- Kendi Kendine Giden Arabalar
- Robotik
- Yüz Algılama
- çalışma alanı Kasa ty
- 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 miktarda veri gerekir. Verilerdeki desenler bir dizi katmanla temsil edilir. Verilerdeki ilişkiler, ağırlık içeren katmanlar arasındaki bağlantılar olarak kodlanır. Ağırlık ne kadar yüksekse ilişki o kadar güçlü olur. Bu katman ve bağlantı serisi, yapay sinir ağları olarak bilinir. Bir ağda ne kadar çok katman olursa o kadar "derin" olur ve bu da onu derin bir sinir ağı haline getirir.
En yaygın olanı Çok Katmanlı Algılama (MLP), Kıvrımlı Sinir Ağı (CNN) ve Yinelenen Sinir Ağı (RNN) olan farklı sinir ağı türleri vardır. En temel olan, bir dizi girişi bir çıkış kümesiyle eşleyen MLP'dir. Bu sinir ağı, verilerin uzamsal veya zaman bileşeni olmadığında iyidir. CNN, verilerde yer alan uzamsal bilgileri işlemek için kıvrımlı 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 ortasında bir burun var mı?). Son olarak, RNN'ler durum veya belleğin kalıcılığının giriş olarak kullanılmasına olanak sağlar. RNN'ler, olayların sıralı sıralamasının ve 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, MAKALEDE açıklanan YOLOv2 modelinin daha kompakt bir sürümü olan Tiny YOLOv2 modelidir: Redmon ve Farhadi tarafından "YOLO9000: Daha İyi, Daha Hızlı, Daha Güçlü". Tiny YOLOv2, Pascal VOC veri kümesi üzerinde eğitilir ve 20 farklı nesne sınıfını tahmin edebilen 15 katmandan oluşur. Tiny YOLOv2 orijinal YOLOv2 modelinin sıkıştırılmış bir sürümü olduğundan, hız ve doğruluk arasında bir denge sağlanır. Modeli oluşturan farklı katmanlar Netron gibi araçlar kullanılarak görselleştirilebilir. Modelin incelenmesi sinir ağını oluşturan tüm katmanlar arasındaki bağlantıların eşlenmesine neden olur ve burada her katman, ilgili giriş/çıkışın boyutlarıyla birlikte katmanın adını içerir. Modelin girişlerini ve çıkışlarını açıklamak için kullanılan veri yapıları, tensor olarak bilinir. Tensor'lar, verileri N boyutlu olarak depolayan kapsayıcılar olarak düşünülebilir. Tiny YOLOv2 söz konusu olduğunda, giriş katmanının adıdır image ve boyut 3 x 416 x 416tensorunu bekler. Çıkış katmanının adıdır grid ve boyutların 125 x 13 x 13çıkış tensorunu oluşturur.

YOLO modeli bir görüntü 3(RGB) x 416px x 416pxalır. Model bu girişi alır ve çıkış oluşturmak için farklı katmanlardan geçirir. Çıkış, giriş görüntüsünü bir 13 x 13 kılavuza böler ve kılavuzdaki her hücre değerlerden oluşur 125 .
ONNX modeli nedir?
Açık Sinir Ağı Değişimi (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 birçok popüler makine öğrenmesi çerçevelerinden birinde modeli eğitebileceğiniz, ONNX biçimine dönüştürebileceğiniz ve ONNX modelini ML.NET gibi farklı bir çerçevede kullanabileceğiniz anlamına gelir. Daha fazla bilgi edinmek için ONNX web sitesini ziyaret edin.

Önceden eğitilmiş Tiny YOLOv2 modeli, katmanların serileştirilmiş bir gösterimi ve bu katmanların öğrenilen desenleri olan ONNX biçiminde depolanır. ML.NET, ve OnnxTransformer NuGet paketleriyle ONNX ile ImageAnalytics birlikte çalışabilirlik elde edilir. Paket, ImageAnalytics bir görüntü alan ve bunu bir tahmin veya eğitim işlem hattına giriş olarak kullanılabilecek sayısal değerlere kodlayan bir dizi dönüşüm içerir. Paket, OnnxTransformer ONNX modeli yüklemek için ONNX Çalışma Zamanı'nı kullanır ve sağlanan girişe göre tahminlerde bulunmak 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 anladığınıza göre, uygulamayı oluşturmanın zamanı geldi.
Konsol uygulaması oluşturma
"ObjectDetection" adlı bir C# Konsol Uygulaması oluşturun. İleri düğmesine tıklayın.
Kullanılacak çerçeve olarak .NET 6'yı seçin. Oluştur düğmesine tıklayın.
Microsoft.ML NuGet Paketini yükleyin:
Dekont
Bu örnek, aksi belirtilmedikçe bahsedilen NuGet paketlerinin en son kararlı sürümünü kullanır.
- Çözüm Gezgini'da projenize sağ tıklayın ve NuGet Paketlerini Yönet'i seçin.
- Paket kaynağı olarak "nuget.org" öğesini seçin, Gözat sekmesini seçin, Microsoft.ML arayın.
- Yükle düğmesini seçin.
- Listelenen paketlerin lisans koşullarını kabul ediyorsanız, Değişiklikleri Önizle iletişim kutusunda Tamam düğmesini ve ardından Lisans Kabulü iletişim kutusunda Kabul Ediyorum düğmesini seçin.
- Microsoft.Windows.Compatibility, Microsoft.ML.ImageAnalytics, Microsoft.ML.OnnxTransformer ve Microsoft.ML.OnnxRuntime için bu adımları yineleyin.
Verilerinizi ve önceden eğitilmiş modelinizi hazırlama
Proje varlıkları dizini zip dosyasını indirin ve sıkıştırmayı açın.
assetsDizini ObjectDetection proje dizininize kopyalayın. Bu dizin ve alt dizinleri, bu öğretici için gereken görüntü dosyalarını (bir sonraki adımda indirip ekleyeceğiniz Tiny YOLOv2 modeli hariç) içerir.ONNX Model Hayvanat Bahçesi'nden Tiny YOLOv2 modelini indirin.
model.onnxDosyayı ObjectDetection projeassets\Modeldizininize kopyalayın ve olarak yeniden adlandırınTinyYolo2_model.onnx. Bu dizin, bu öğretici için gereken modeli içerir.Çözüm Gezgini varlık dizinindeki ve alt dizinlerdeki dosyaların her birine sağ tıklayın ve Özellikler'i seçin. Gelişmiş'in altında, Daha yeniyse Çıkış Dizinine Kopyala değerini Kopyala olarak değiştirin.
Sınıf oluşturma ve yolları tanımlama
Program.cs dosyasını açın ve dosyanın en üstüne aşağıdaki ek using deyimleri ekleyin:
using System.Drawing;
using System.Drawing.Drawing2D;
using ObjectDetection.YoloParser;
using ObjectDetection.DataStructures;
using ObjectDetection;
using Microsoft.ML;
Ardından, çeşitli varlıkların yollarını tanımlayın.
İlk olarak, Program.cs dosyasının en altında yöntemini oluşturun
GetAbsolutePath.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'da 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, "DataStructures" olarak adlandırın.
Giriş veri sınıfınızı yeni oluşturulan DataStructures dizininde oluşturun.
Çözüm Gezgini'da DataStructures dizinine 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ı ImageNetData.cs olarak değiştirin. Ardından Ekle düğmesini seçin.
ImageNetData.cs dosyası kod düzenleyicisinde açılır. ImageNetData.cs dosyasının en üstüne aşağıdaki
usingdeyimi 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
ImageNetDataaşağıdaki kodu ImageNetData.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) }); } }ImageNetDatagiriş görüntüsü 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,
ImageNetDatabelirtilen yolda depolananimageFolderbirden çok görüntü dosyasını yükleyen ve bunları bir nesne koleksiyonuImageNetDataolarak döndüren bir yöntemReadFromFileiçerir.
DataStructures dizininde tahmin sınıfınızı oluşturun.
Çözüm Gezgini'da DataStructures dizinine 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ı ImageNetPrediction.cs olarak değiştirin. Ardından Ekle düğmesini seçin.
ImageNetPrediction.cs dosyası kod düzenleyicisinde açılır. ImageNetPrediction.cs dosyasının en üstüne aşağıdaki
usingdeyimi ekleyin:using Microsoft.ML.Data;Mevcut sınıf tanımını kaldırın ve sınıfı için
ImageNetPredictionaşağıdaki kodu ImageNetPrediction.cs dosyasına ekleyin:public class ImageNetPrediction { [ColumnName("grid")] public float[] PredictedLabels; }ImageNetPredictiontahmin veri sınıfıdır ve aşağıdakifloat[]alana sahiptir:PredictedLabelsbir görüntüde algılanan sınırlayıcı kutuların her biri için boyutları, nesnelik puanını ve sınıf olasılıklarını içerir.
Değişkenleri başlatma
MLContext sınıfı, tüm ML.NET işlemleri için bir başlangıç noktasıdır ve başlatma mlContext işlemi, model oluşturma iş akışı nesneleri arasında paylaşılabilen yeni bir ML.NET ortamı oluşturur. Entity Framework'tekine DBContext benzer, kavramsal olarak.
mlContext Alanının altına aşağıdaki satırı ekleyerek değişkenini outputFolder yeni bir örneğiyle MLContext başlatın.
MLContext mlContext = new MLContext();
İşlem sonrası model çıkışları için ayrıştırıcı oluşturma
Model, her kılavuz hücresinin 32px x 32pxolduğu bir görüntüyü bir 13 x 13 kılavuzda segmentlere ayırır. Her kılavuz hücresi 5 olası nesne sınırlayıcı kutu içerir. Sınırlayıcı kutuda 25 öğe vardır:

xsınırlayıcı kutu merkezinin ilişkili olduğu kılavuz hücresine göre x konumu.ysınırlayıcı kutu merkezinin ilişkili olduğu kılavuz hücresine göre y konumu.wsınırlayıcı kutunun genişliği.hsınırlayıcı kutunun yüksekliği.onesnenin sınırlayıcı kutu içinde var olduğu güvenilirlik değeri( nesnelik 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ı.
Toplamda, 5 sınırlayıcı kutunun her birini açıklayan 25 öğe, her kılavuz hücresinde bulunan 125 öğeyi oluşturur.
Önceden eğitilmiş ONNX modeli tarafından oluşturulan çıkış, boyutları 125 x 13 x 13olan bir tensörün öğelerini temsil eden bir kayan uzunluk 21125dizisidir. Model tarafından oluşturulan tahminleri bir tensora dönüştürmek için bazı işlem sonrası işler gereklidir. Bunu yapmak için çıkışı ayrıştırmaya yardımcı olacak 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'da 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 çıkışı, görüntüdeki sınırlayıcı nesne 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 ardından 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. Ardından Ekle düğmesini seçin.
DimensionsBase.cs dosyası kod düzenleyicisinde açılır. Tüm
usingdeyimleri ve var olan sınıf tanımını kaldırın.Sınıfı için
DimensionsBaseaşağıdaki kodu DimensionsBase.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ğıdakifloatözelliklere sahiptir:Xnesnenin x ekseni boyunca konumunu içerir.Ynesnenin y ekseni boyunca konumunu içerir.Heightnesnesinin 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 ardından 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. Ardından Ekle düğmesini seçin.
YoloBoundingBox.cs dosyası kod düzenleyicisinde açılır. YoloBoundingBox.cs dosyasının en üstüne aşağıdaki
usingdeyimi ekleyin:using System.Drawing;Mevcut sınıf tanımının hemen üstüne, ilgili sınırlayıcı kutunun boyutlarını içerecek şekilde sınıfından
DimensionsBasedevralan adlıBoundingBoxDimensionsyeni bir sınıf tanımı ekleyin.public class BoundingBoxDimensions : DimensionsBase { }Mevcut
YoloBoundingBoxsınıf tanımını kaldırın ve yoloBoundingBox.cs dosyasına sınıfı içinYoloBoundingBoxaşağıdaki kodu 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ı kutuda algılanan nesne sınıfını içerir.Confidencesınıfının güvenilirliğini içerir.Rectsınırlayıcı kutunun boyutlarının dikdörtgen gösterimini içerir.BoxColor, görüntü üzerinde çizim yapmak için kullanılan ilgili sınıfla ilişkili rengi içerir.
Ayrıştırıcıyı oluşturma
Boyutlar ve sınırlayıcı kutuları için sınıflar oluşturulduğuna göre, ayrıştırıcıyı oluşturmanın zamanı geldi.
Çözüm Gezgini yoloParser dizinine 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ı YoloOutputParser.cs olarak değiştirin. Ardından Ekle düğmesini seçin.
YoloOutputParser.cs dosyası kod düzenleyicisinde açılır. YoloOutputParser.cs dosyasının en üstüne aşağıdaki
usingdeyimleri ekleyin:using System; using System.Collections.Generic; using System.Drawing; using System.Linq;Mevcut
YoloOutputParsersınıf tanımının içine, görüntüdeki her bir hücrenin boyutlarını içeren iç içe geçmiş bir sınıf ekleyin. Sınıf tanımınınCellDimensionsen üstündekiYoloOutputParsersınıfındanDimensionsBasedevralan sınıf için aşağıdaki kodu ekleyin.class CellDimensions : DimensionsBase { }Sınıf tanımının
YoloOutputParseriçine aşağıdaki sabitleri ve alanı 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ünün bölündüğü kılavuzdaki satır sayısıdır.COL_COUNT, görüntünün bölündüğü kılavuzdaki sütunların sayısıdır.CHANNEL_COUNT, kılavuzun bir hücresinde yer alan toplam değer sayısıdır.BOXES_PER_CELLhücredeki sınırlayıcı kutuların sayısıdır,BOX_INFO_FEATURE_COUNTbir kutunun içindeki özelliklerin sayısıdır (x,y,yükseklik,genişlik,güvenilirlik).CLASS_COUNT, her sınırlayıcı kutuda yer alan sınıf tahminlerinin 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, giriş görüntüsünü boyutunda
13 x 13bir hücre kılavuzuna böler416px x 416px. Her hücre içerir32px x 32px. Her hücrenin içinde her birinde 5 özellik (x, y, width, height, confidence) içeren 5 sınırlayıcı kutu vardır. Buna ek olarak, her sınırlayıcı kutu sınıfların her birinin olasılığını içerir ve bu durumda 20'dir. Bu nedenle, her hücre 125 bilgi parçası içerir (5 özellik + 20 sınıf olasılığı).
5 sınırlayıcı kutunun tümü için aşağıda channelStride yer işaretlerinin listesini oluşturun:
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
};
Tutturucular, sınırlayıcı kutuların önceden tanımlanmış yükseklik ve genişlik oranlarıdır. Bir model tarafından algılanan nesne veya sınıfların çoğu benzer oranlara sahiptir. Sınırlayıcı kutular oluşturma söz konusu olduğunda bu değerlidir. Sınırlayıcı kutuları tahmin etmek yerine, önceden tanımlanmış boyutlardan uzaklık hesaplanır, bu nedenle sınırlayıcı kutuyu tahmin etmek için gereken hesaplama azaltılır. Bu yer işareti oranları genellikle kullanılan veri kümesine göre hesaplanır. Bu durumda, veri kümesi bilindiğinden ve değerler önceden hesaplandığından, sabit kodlanabilir.
Ardından, modelin tahmin edeceği 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.
Etiket listenizi altına anchorsekleyin.
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şkilendirilmiş renkler vardır. sınıf renklerinizi aşağıdakine 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
İşlem sonrası aşamasında bir dizi adım vardır. Buna yardımcı olmak için çeşitli yardımcı yöntemler kullanılabilir.
Ayrıştırıcı tarafından kullanılan yardımcı yöntemler şunlardır:
Sigmoid0 ile 1 arasında bir sayı veren sigmoid işlevini uygular.Softmaxgiriş vektörlerini bir olasılık dağılımına normalleştirir.GetOffsettek boyutlu model çıkışındaki öğeleri bir125 x 13 x 13tensordaki ilgili konuma eşler.ExtractBoundingBoxesmodel çıktısından yöntemini kullanarakGetOffsetsınırlayıcı kutu boyutlarını ayıklar.GetConfidencemodelin bir nesne algılayıp yüzdeye dönüştürmek için işlevini kullandığındanSigmoidne kadar emin olduğunu belirten güvenilirlik değerini ayıklar.MapBoundingBoxToCellsınırlayıcı kutu boyutlarını kullanır ve bunları görüntüdeki ilgili hücreye eşler.ExtractClassesyöntemini kullanarakGetOffsetmodel çıkışından sınırlayıcı kutu için sınıf tahminlerini ayıklar ve yöntemini kullanarak bunları bir olasılık dağılımınaSoftmaxdönüştürür.GetTopResulten yüksek olasılıkla tahmin edilen sınıflar listesinden sınıfı seçer.IntersectionOverUniondaha düşük olasılıklarla örtüşen sınırlayıcı kutuları filtreler.
Listenizin altına tüm yardımcı yöntemlerin classColorskodunu ekleyin.
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);
}
Yardımcı yöntemlerin tümünü tanımladıktan sonra, bunları kullanarak model çıkışını işlemenin zamanı geldi.
yönteminin IntersectionOverUnion altında, model tarafından oluşturulan çıkışı işlemek için yöntemini oluşturun ParseOutputs .
public IList<YoloBoundingBox> ParseOutputs(float[] yoloModelOutputs, float threshold = .3F)
{
}
Sınırlayıcı kutularınızı depolamak ve yönteminin ParseOutputs içinde değişkenler tanımlamak için bir liste oluşturun.
var boxes = new List<YoloBoundingBox>();
Her resim bir hücre kılavuzuna 13 x 13 ayrılır. Her hücre beş sınırlayıcı kutu içerir. değişkeninin boxes altına, her hücredeki 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ç döngünün içinde, geçerli kutunun tek boyutlu model çıkışındaki başlangıç konumunu hesaplayın.
var channel = (box * (CLASS_COUNT + BOX_INFO_FEATURE_COUNT));
Bunun hemen altında, geçerli sınırlayıcı kutunun boyutlarını almak için yöntemini kullanın ExtractBoundingBoxDimensions .
BoundingBoxDimensions boundingBoxDimensions = ExtractBoundingBoxDimensions(yoloModelOutputs, row, column, channel);
Ardından geçerli sınırlayıcı kutunun güvenilirliğini elde etmek için yöntemini kullanın GetConfidence .
float confidence = GetConfidence(yoloModelOutputs, row, column, channel);
Bundan sonra, geçerli sınırlayıcı kutuyu işlenen geçerli hücreyle eşlemek için yöntemini kullanın MapBoundingBoxToCell .
CellDimensions mappedBoundingBox = MapBoundingBoxToCell(row, column, box, boundingBoxDimensions);
Daha fazla işlem yapmadan önce güvenilirlik değerinizin sağlanan eşikten büyük olup olmadığını denetleyin. Aksi takdirde, sonraki sınırlayıcı kutuyu işleyin.
if (confidence < threshold)
continue;
Aksi takdirde, çıkışı işlemeye devam edin. Sonraki adım, yöntemini kullanarak geçerli sınırlayıcı kutu için tahmin edilen sınıfların olasılık dağılımını almaktır ExtractClasses .
float[] predictedClasses = ExtractClasses(yoloModelOutputs, row, column, channel);
Ardından geçerli kutu için en yüksek olasılıkla sınıfın değerini ve dizinini almak ve puanını hesaplamak için yöntemini kullanın GetTopResult .
var (topResultIndex, topResultScore) = GetTopResult(predictedClasses);
var topScore = topResultScore * confidence;
için değerini topScore bir kez daha yalnızca belirtilen eşiğin üzerinde olan sınırlayıcı kutuları koruyun.
if (topScore < threshold)
continue;
Son olarak, geçerli sınırlayıcı kutu eşiği aşarsa yeni BoundingBox bir nesne oluşturun ve listeye boxes 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 döndürebilirsiniz boxes . yöntemindeki en dış for-loop öğesinin altına aşağıdaki return deyimini ParseOutputs ekleyin.
return boxes;
Örtüşen kutuları filtrele
Artık model çıkışından son derece güvenli sınırlayıcı kutuların tümü ayıklandığına göre, çakışan görüntüleri kaldırmak için ek filtreleme yapılması gerekir. yönteminin ParseOutputs altına adlı FilterBoundingBoxes bir yöntem ekleyin:
public IList<YoloBoundingBox> FilterBoundingBoxes(IList<YoloBoundingBox> boxes, int limit, float threshold)
{
}
yönteminin FilterBoundingBoxes içinde, algılanan kutuların boyutuna eşit bir dizi oluşturarak ve tüm yuvaları etkin veya işlemeye hazır olarak işaretleyerek başlayı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üvene göre azalan düzende sıralayın.
var sortedBoxes = boxes.Select((b, i) => new { Box = b, Index = i })
.OrderByDescending(b => b.Box.Confidence)
.ToList();
Bundan sonra, filtrelenen sonuçları tutmak için bir liste oluşturun.
var results = new List<YoloBoundingBox>();
Sınırlayıcı kutuların her biri üzerinde yineleme yaparak her sınırlayıcı kutuyu işlemeye başlayın.
for (int i = 0; i < boxes.Count; i++)
{
}
Bu for-loop içinde geçerli sınırlayıcı kutunun işlenip işlenemeyeceğini denetleyin.
if (isActiveBoxes[i])
{
}
Öyleyse, sınırlayıcı kutuyu sonuç listesine ekleyin. Sonuçlar ayıklanacak kutuların belirtilen sınırını aşarsa döngüden çıkın. Aşağıdaki kodu if-deyiminin içine ekleyin.
var boxA = sortedBoxes[i].Box;
results.Add(boxA);
if (results.Count >= limit)
break;
Aksi takdirde, bitişik sınırlayıcı kutularına bakın. Kutu sınırı denetiminin altına aşağıdaki kodu ekleyin.
for (var j = i + 1; j < boxes.Count; j++)
{
}
İlk kutu gibi, bitişik kutu etkinse veya işlenmeye hazırsa, ilk kutunun ve ikinci kutunun belirtilen eşiği aşıp aşmadığını denetlemek için yöntemini kullanın IntersectionOverUnion . Aşağıdaki kodu en iç döngünüze 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ı denetleen en içteki for-loop'un dışında, işlenecek kalan sınırlayıcı kutu olup olmadığına bakın. Aksi takdirde, dış for-loop'un dışına çıkın.
if (activeCount <= 0)
break;
Son olarak, yöntemin ilk for-döngüsü FilterBoundingBoxes dışında sonuçları döndürür:
return results;
Harika! Şimdi puanlama için modelle birlikte bu kodu kullanma zamanı geldi.
Puanlama için modeli kullanma
İşlem sonrası işlemlerde olduğu gibi puanlama adımlarında da birkaç adım vardır. Bu konuda yardımcı olmak için projenize puanlama mantığını içerecek bir sınıf ekleyin.
Çözüm Gezgini'de 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. Ardından Ekle düğmesini seçin.
OnnxModelScorer.cs dosyası kod düzenleyicisinde açılır. OnnxModelScorer.cs dosyasının en üstüne aşağıdaki
usingdeyimleri ekleyin:using System; using System.Collections.Generic; using System.Linq; using Microsoft.ML; using Microsoft.ML.Data; using ObjectDetection.DataStructures; using ObjectDetection.YoloParser;Sınıf tanımının
OnnxModelScoreriçine 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>();Bunun hemen altında, önceden tanımlanmış değişkenleri başlatacak sınıf için
OnnxModelScorerbir 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. Modelin girişi olarak beklenen yükseklik ve genişliği içerecek şekilde adlı
ImageNetSettingsbir yapı oluşturun.public struct ImageNetSettings { public const int imageHeight = 416; public const int imageWidth = 416; }Bundan sonra, modelin giriş ve çıkış katmanlarının adlarını içeren adlı
TinyYoloModelSettingsbaşka bir yapı oluşturun. Modelin giriş ve çıkış katmanlarının adını görselleştirmek için Netron gibi 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ınOnnxModelScoreriçinde yöntemini oluşturun.private ITransformer LoadModel(string modelLocation) { }yönteminin
LoadModeliçine gü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ının, yöntem çağrıldığında üzerinde çalışacak veri şemasını
Fitbilmesi gerekir. Bu durumda eğitime benzer bir süreç kullanılır. Ancak, gerçek bir eğitim olmadığından, boşIDataViewbir kullanmak kabul edilebilir. boş bir listeden işlem hattı için yeniIDataViewbir oluşturun.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ü Bit Eşlem olarak yükler.ResizeImagesgörüntüyü belirtilen boyuta (bu örnekte)416 x 416yeniden ölçekler.ExtractPixelsgörüntünün piksel gösterimini Bit Eşlem'den sayısal vektöre değiştirir.ApplyOnnxModelONNX modelini yükler ve sağlanan verilere puan vermek için bu modeli kullanır.
değişkeninin altındaki
datayöntemindeLoadModelişlem hattınızı tanımlayın.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 modelin örneğini oluşturma zamanı geldi.
Fitİşlem hattında yöntemini çağırın ve daha fazla işlem için döndürebilirsiniz.var model = pipeline.Fit(data); return model;
Model yüklendikten sonra tahminlerde bulunmak için kullanılabilir. Bu işlemi kolaylaştırmak için yönteminin LoadModel altında adlı PredictDataUsingModel bir yöntem oluşturun.
private IEnumerable<float[]> PredictDataUsingModel(IDataView testData, ITransformer model)
{
}
içinde PredictDataUsingModelgünlüğe kaydetmek 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 puan etmek için yöntemini kullanın Transform .
IDataView scoredData = model.Transform(testData);
Tahmin edilen olasılıkları ayıklayın ve ek işlem için bunları döndürin.
IEnumerable<float[]> probabilities = scoredData.GetColumn<float[]>(TinyYoloModelSettings.ModelOutput);
return probabilities;
Her iki adım da ayarlandıklarına göre, bunları tek bir yöntemde birleştirin. yönteminin PredictDataUsingModel altına adlı Scoreyeni bir yöntem ekleyin.
public IEnumerable<float[]> Score(IDataView data)
{
var model = LoadModel(modelLocation);
return PredictDataUsingModel(data, model);
}
Neredeyse bitti! Şimdi hepsini kullanma zamanı.
Nesneleri algılama
Tüm kurulum tamamlandıktan sonra bazı nesneleri algılamanın zamanı geldi.
Model çıkışlarını puanlayıp ayrıştırma
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şlayın. İlk olarak, verileri içine IDataViewyükleyin.
IEnumerable<ImageNetData> images = ImageNetData.ReadFromFile(imagesFolder);
IDataView imageDataView = mlContext.Data.LoadFromEnumerable(images);
Ardından bir örneği OnnxModelScorer oluşturun ve bunu kullanarak yüklenen verileri puanlayın.
// Create instance of model scorer
var modelScorer = new OnnxModelScorer(imagesFolder, modelFilePath, mlContext);
// Use model to score data
IEnumerable<float[]> probabilities = modelScorer.Score(imageDataView);
Şimdi işlem sonrası adımının zamanı geldi. örneğini YoloOutputParser oluşturun ve model çıkışını işlemek için kullanın.
YoloOutputParser parser = new YoloOutputParser();
var boundingBoxes =
probabilities
.Select(probability => parser.ParseOutputs(probability))
.Select(boxes => parser.FilterBoundingBoxes(boxes, 5, .5F));
Model çıktısı işlendikten sonra, resimlere sınırlayıcı kutuları çizmenin zamanı geldi.
Tahminleri görselleştirme
Model görüntüleri puanladıktan ve çıkışlar işlendikten sonra, sınırlayıcı kutuların görüntüye çizilmesi gerekir. Bunu yapmak için, Program.cs dosyasının içindeki yönteminin GetAbsolutePath altına adlı DrawBoundingBox bir yöntem ekleyin.
void DrawBoundingBox(string inputImageLocation, string outputImageLocation, string imageName, IList<YoloBoundingBox> filteredBoundingBoxes)
{
}
İlk olarak, görüntüyü yükleyin ve yöntemindeki yükseklik ve genişlik boyutlarını DrawBoundingBox alın.
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 yineleme yapmak için her biri için bir döngü oluşturun.
foreach (var box in filteredBoundingBoxes)
{
}
For-each döngüsünün içinde sınırlayıcı kutunun boyutlarını alın.
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 416 x 416karşılık geldiği için sınırlayıcı kutu boyutlarını resmin gerçek boyutuyla eşleşecek ş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üvenilirliğini içerir.
string text = $"{box.Label} ({(box.Confidence * 100).ToString("0")}%)";
Resmin üzerine çizim yapmak için resmi bir Graphics nesneye dönüştürün.
using (Graphics thumbnailGraphic = Graphics.FromImage(image))
{
}
Kod bloğunun using içinde grafiğin Graphics nesne ayarlarını 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 FillRectangle metni içerecek şekilde sınırlayıcı kutunun üzerinde bir dikdörtgen oluşturun ve doldurun. Bu, metnin karşıtlığını artırmaya 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 DrawRectangle yöntemlerini kullanarak DrawString resimdeki metni ve sınırlayıcı kutuyu çizin.
thumbnailGraphic.DrawString(text, drawFont, fontBrush, atPoint);
// Draw bounding box on image
thumbnailGraphic.DrawRectangle(pen, x, y, width, height);
For-each döngüsünün dışında, içindeki görüntüleri outputFolderkaydetmek için kod ekleyin.
if (!Directory.Exists(outputImageLocation))
{
Directory.CreateDirectory(outputImageLocation);
}
image.Save(Path.Combine(outputImageLocation, imageName));
Uygulamanın çalışma zamanında beklendiği gibi tahminlerde bulunduğunu belirten ek geri bildirim için, algılanan nesnelerin konsoluna çıkışı için Program.cs dosyasında yönteminin altına DrawBoundingBox adlı LogDetectedObjects bir yöntem ekleyin.
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("");
}
Artık tahminlerden görsel geri bildirim oluşturmak için yardımcı yöntemleriniz olduğuna göre, puanlanan görüntülerin her birini yinelemek için bir for-loop ekleyin.
for (var i = 0; i < images.Count(); i++)
{
}
for-döngüsü içinde, görüntü dosyasının adını ve onunla ilişkili sınırlayıcı kutuları alın.
string imageFileName = images.ElementAt(i).Label;
IList<YoloBoundingBox> detectedObjects = boundingBoxes.ElementAt(i);
Bunun altında, görüntüdeki sınırlayıcı kutuları çizmek için yöntemini kullanın DrawBoundingBox .
DrawBoundingBox(imagesFolder, outputFolder, imageFileName, detectedObjects);
Son olarak, konsola LogDetectedObjects tahminleri çıkarmak için yöntemini kullanın.
LogDetectedObjects(imageFileName, detectedObjects);
try-catch deyiminden sonra, işlemin çalışmasının tamam olduğunu belirtmek için ek mantık ekleyin.
Console.WriteLine("========= End of Process..Hit any Key ========");
İşte hepsi bu!
Sonuçlar
Önceki adımları izledikten sonra konsol uygulamanızı (Ctrl + F5) çalıştırın. Sonuçlarınız aşağıdaki çıkışa benzer olmalıdır. Uyarılar veya işleme iletileri görebilirsiniz, ancak bu iletiler netlik 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ı kutuları olan görüntüleri görmek için dizine assets/images/output/ gidin. aşağıda, işlenen görüntülerden birinden bir örnek verilmiştir.

Tebrikler! Artık ML.NET'de önceden eğitilmiş ONNX bir modeli yeniden kullanarak nesne algılama için bir makine öğrenmesi modelini başarıyla oluşturdunuz.
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üklü bir modelle nesneleri algılama
Genişletilmiş nesne algılama örneğini keşfetmek için Machine Learning örnekleri GitHub deposuna göz atın.