Kılavuz: ML.NET ile Custom Vision ONNX modeli kullanarak bir görüntüyü kategorilere ayırma

Microsoft Özel Görüntü İşleme hizmetinde eğitilmiş bir ONNX modeli kullanarak görüntülerdeki nesneleri algılamak için ML.NET kullanmayı öğrenin.

Microsoft Özel Görüntü İşleme hizmeti, karşıya yüklediğiniz görüntülere göre modeli eğiten bir yapay zeka hizmetidir. Ardından modeli ONNX biçimine aktarabilir ve tahminlerde bulunmak için ML.NET kullanabilirsiniz.

Bu eğitimde şunları öğreniyorsunuz:

  • ONNX modeli oluşturmak için Özel Görüntü İşleme hizmetini kullanma
  • ONNX modelini ML.NET işlem hattına ekleme
  • ML.NET modelini eğitin
  • Test görüntülerinde durdurma işaretlerini algılama

Önkoşullar

Modeli oluşturma

Özel Görüntü İşleme projesini oluşturma

Microsoft Özel Görüntü İşleme hizmetinde oturum açın ve Yeni Proje'yi seçin.

Yeni Proje iletişim kutusunda aşağıdaki gerekli öğeleri doldurun:

  • Özel Görüntü İşleme projesinin AdınıStopSignDetection olarak ayarlayın.
  • Kullanacağınız Kaynağı seçin. Bu, Özel Görüntü İşleme projesi için oluşturulacak bir Azure kaynağıdır. Hiçbiri listelenmiyorsa , Yeni oluştur bağlantısı seçilerek oluşturulabilir.
  • Proje türünüNesne Algılama olarak ayarlayın.
  • Görüntü başına bir sınıf olacağından Sınıflandırma TürleriniÇok Sınıflı olarak ayarlayın.
  • Etki AlanınıGenel (sıkıştırılmış) [S1] olarak ayarlayın. Kompakt etki alanı, ONNX modelini indirmenize olanak tanır.
  • Dışarı aktarma özellikleri için, ONNX modelini dışarı aktarmaya izin vermek için Temel platformlar'ı seçin.

Yukarıdaki alanlar doldurulduktan sonra Proje oluştur'u seçin.

Resim ekleme

  1. Proje oluşturulduktan sonra modelin eğitileceği görüntüleri eklemeye başlamak için Görüntü ekle'yi seçin. İndirdiğiniz dur işareti görüntülerini seçin.
  2. Gösterilen ilk resmi seçin. Görüntüde modelin algılamasını istediğiniz nesneleri seçebilirsiniz. Görüntüdeki dur işaretini seçin. Açılan pencere, etiketi stop-sign olarak görüntüler ve ayarlar.
  3. Kalan tüm görüntüler için yineleyin. Bazı görüntülerde birden fazla dur işareti vardır, bu nedenle görüntülerdeki tüm resimleri işaretlemeyi unutmayın.

Modeli eğitin

Resimler yüklendi ve etiketlendi, şimdi model eğitilebilir. Eğit'i seçin.

Ne tür bir eğitimin kullanılacağını soran bir açılır pencere görüntülenir. Hızlı eğitim'i ve ardından Eğit'i seçin.

ONNX modelini indirme

Eğitim tamamlandıktan sonra Dışarı Aktar düğmesine tıklayın. Açılan pencere görüntülendiğinde ONNX modelini indirmek için ONNX'i seçin.

ONNX modelini inceleme

İndirilen ONNX dosyasının sıkıştırmasını açın. Klasörde birkaç dosya bulunur, ancak bu öğreticide kullanacağınız ikisi şunlardır:

  • labels.txt, Özel Görüntü İşleme hizmetinde tanımlanan etiketleri içeren bir metin dosyasıdır.
  • model.onnx, ML.NET tahminlerde bulunmak için kullanacağınız ONNX modelidir.

ML.NET işlem hattını oluşturmak için giriş ve çıkış sütun adlarının adları gerekir. Bu bilgileri almak için, ONNX modellerini analiz edip mimarilerini gösterebilen bir web ve masaüstü uygulaması olan Netron'ı kullanın.

  1. Netron'un web veya masaüstü uygulamasını kullanırken uygulamada ONNX modelini açın. Açıldıktan sonra bir grafik görüntüler. Bu grafik, tahminler için ML.NET işlem hattını oluşturmak için ihtiyacınız olan birkaç şeyi bildirir.

    • Giriş sütunu adı - ML.NET ONNX modeli uygulanırken gereken giriş sütunu adı.

      Netron Giriş Sütunu

    • Çıkış sütun adı - ML.NET ONNX modeli uygulanırken gereken çıkış sütun adı.

      Netron Çıkış Sütunu

    • Görüntü boyutu - ML.NET işlem hattındaki görüntüleri yeniden boyutlandırırken gereken boyut.

      Netron Görüntü Boyutu

C# konsol projesi oluşturma

  1. Visual Studio'da "StopSignDetection" adlı bir C# Konsol Uygulaması oluşturun. Hedef çerçeve olarak .NET 8'i seçin.

  2. Proje için aşağıdaki NuGet paketlerini yükleyin:

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

    Uyarı

    Bu örnek, aksi belirtilmedikçe bahsedilen NuGet paketlerinin en son kararlı sürümünü kullanır.

ONNX modeline başvurma

Visual Studio Çözüm Gezgini'nde ONNX modelindeki (labels.txt ve model.onnx) iki dosyayı bulun. Bunlara sağ tıklayın ve Özellikler penceresinde Çıkış dizinine kopyala'yıdaha yeniyse Kopyala olarak ayarlayın.

Giriş ve tahmin sınıfları oluşturma

  1. Projenize yeni bir sınıf ekleyin ve adını verin StopSignInput. Ardından aşağıdaki yapıyı sınıfına ekleyin:

    public struct ImageSettings
    {
        public const int imageHeight = 320;
        public const int imageWidth = 320;
    }
    
  2. Ardından aşağıdaki özelliği sınıfına ekleyin.

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

    özelliği, Image tahmin için kullanılan görüntünün bit eşlemini içerir. ImageType özniteliği ML.NET özelliğin Netron kullanılarak belirlenen 320 ve 320 boyutlarına sahip bir görüntü olduğunu söyler.

  3. Projenize başka bir sınıf ekleyin ve adını verin StopSignPrediction. Ardından aşağıdaki özellikleri sınıfına ekleyin.

    public class StopSignPrediction
    {
        [ColumnName("detected_classes")]
        public long[] PredictedLabels { get; set; }
    
        [ColumnName("detected_boxes")]
        public float[] BoundingBoxes { get; set; }
    
        [ColumnName("detected_scores")]
        public float[] Scores { get; set; }
    }
    

    özelliği, PredictedLabels algılanan her nesne için etiket tahminlerini içerir. Tür bir float dizisidir, bu nedenle dizideki her öğe her etiketin tahminidir. ColumnName özniteliği, ML.NET modeldeki bu sütunun verilen ad olduğunu (olandetected_classes) bildirir.

    BoundingBoxes özelliği, algılanan her nesne için sınırlayıcı kutular içerir. Tür, bir float dizisidir ve her algılanan nesne, sınırlayıcı kutu için dizide dört öğe ile temsil edilir. ColumnName özniteliği, ML.NET modeldeki bu sütunun verilen ad olduğunu (olandetected_boxes) bildirir.

    özelliği, Scores tahmin edilen her nesnenin güvenilirlik puanlarını ve etiketini içerir. Tür bir float dizisidir, bu nedenle dizideki her öğe her etiketin güvenilirlik puanıdır. ColumnName özniteliği, ML.NET modeldeki bu sütunun verilen ad olduğunu (olandetected_scores) bildirir.

Tahminlerde bulunmak için modeli kullanma

Using yönergeleri ekle

Program.cs dosyasında, dosyanın en üstüne aşağıdaki using yönergeleri ekleyin.

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

Nesneler oluşturma

  1. MLContext Nesnesini oluşturun.

    var context = new MLContext();
    
  2. IDataView Yeni bir boş StopSignInput listeyle bir oluşturun.

    var data = context.Data.LoadFromEnumerable(new List<StopSignInput>());
    
  3. Tutarlılık için, tahmin edilen görüntüleri derleme yoluna kaydedin.

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

İşlem hattını oluştur

Boş IDataView oluşturulduktan sonra işlem hattı, yeni görüntülerin tahminlerini yapacak şekilde oluşturulabilir. İşlem hattı birkaç adımdan oluşur:

  1. Gelen görüntüleri yeniden boyutlandırın.

    Tahmin için modele gönderilen görüntü genellikle modelde eğitilen görüntülere göre farklı bir en boy oranında olur. Doğru tahminler için görüntünün tutarlı olmasını sağlamak için görüntüyü 320x320 olarak yeniden boyutlandırın. Bunu yapmak için yöntemini kullanın ResizeImages ve özelliğinin imageColumnName adı olarak ayarlayınStopSignInput.Image.

    var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: "image_tensor", imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight, inputColumnName: nameof(StopSignInput.Image))
    
  2. Görüntünün piksellerini ayıklayın.

    Resim yeniden boyutlandırıldıktan sonra görüntünün piksellerini ayıklamanız gerekir. ExtractPixels yöntemini işlem hattınıza ekleyin ve parametresini kullanarak piksellerin çıkışını almak için sütunun outputColumnName adını belirtin.

    .Append(context.Transforms.ExtractPixels(outputColumnName: "image_tensor"))
    
  3. Tahminde bulunmak için görüntüye ONNX modelini uygulayın. Bu işlem birkaç parametre alır:

    • modelFile - ONNX model dosyasının yolu
    • outputColumnNames - Netron'da ONNX modeli analiz edilirken bulunabilen, tüm çıkış sütun adlarını içeren bir dize dizisi.
    • inputColumnNames - Netron'da ONNX modelini analiz ederken de bulunabilen, tüm giriş sütun adının adlarını içeren bir dize dizisi.

    Important

    Yalnızca güvenilir kaynaklardan modelleri uygulayın. Güvenilmeyen kaynaklardan model uygulamak bir güvenlik riskidir.

    .Append(context.Transforms.ApplyOnnxModel(outputColumnNames: new string[] { "detected_boxes", "detected_scores", "detected_classes" }, inputColumnNames: new string[] { "image_tensor" }, modelFile: "./Model/model.onnx"));
    

Modeli sığdırma

Artık bir işlem hattı tanımladığınıza göre, ML.NET modelini oluşturmak için bunu kullanabilirsiniz. Fit İşlem hattında yöntemini kullanın ve boş IDataViewöğesini geçirin.

var model = pipeline.Fit(data);

Ardından tahmin yapmak için modeli kullanarak bir tahmin altyapısı oluşturun. Bu genel bir yöntemdir, bu nedenle daha önce oluşturulan StopSignInput ve StopSignPrediction sınıflarını alır.

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

Etiketleri ayıkla

Model çıkışlarını etiketleriyle eşlemek için Özel Görüntü İşleme tarafından sağlanan etiketleri ayıklamanız gerekir. Bu etiketler, ONNX modeliyle zip dosyasında yer alan labels.txt dosyasında yer alır.

dosyasını oluşturan ReadAllLines tüm etiketleri okumak için yöntemini çağırın.

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

Test görüntüsünde tahmin

Artık modeli kullanarak yeni görüntülerle ilgili tahminde bulunabilirsiniz. Projede tahminlerde bulunmak için kullanabileceğiniz bir test klasörü vardır. Bu klasör, Unsplash'ten dur işareti içeren iki rastgele resim içerir. Bir görüntüde bir dur işareti, diğerinde ise iki durdurma işareti vardır. dizinindeki GetFiles görüntülerin dosya yollarını okumak için yöntemini kullanın.

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

Modelle bir tahminde bulunmak ve sonucu çıkarmak için dosya yollarında döngü yapın.

  1. Test görüntüleri arasında döngü yapmak için bir foreach döngü oluşturun.

    Bitmap testImage;
    
    foreach (var image in testFiles)
    {
    
    }
    
  2. Döngüde foreach , özgün test görüntüsünün adına göre tahmin edilen görüntü adını oluşturun.

    var predictedImage = $"{Path.GetFileName(image)}-predicted.jpg";
    
  3. Ayrıca döngüde foreach görüntüden bir FileStream oluşturun ve bunu öğesine Bitmapdönüştürün.

    using (var stream = new FileStream(image, FileMode.Open))
    {
        testImage = (Bitmap)Image.FromStream(stream);
    }
    
  4. Ayrıca döngüde foreach , tahmin altyapısında yöntemini çağırın Predict .

    var prediction = predictionEngine.Predict(new StopSignInput { Image = testImage });
    
  5. Tahminle sınırlayıcı kutuları alabilirsiniz. Modelin Chunk algılanan nesne sayısını belirlemek için yöntemini kullanın. Bunu yapmak için tahmin edilen sınırlayıcı kutuların sayısını alın ve bunu tahmin edilen etiket sayısına bölün. Örneğin, bir görüntüde üç nesne algılandıysa, BoundingBoxes dizisinde 12 öğe ve üç tahmin edilen etiket bulunur. Yöntemi Chunk daha sonra her nesne için sınırlayıcı kutuları temsil etmek için dört üç dizi verir.

    var boundingBoxes = prediction.BoundingBoxes.Chunk(prediction.BoundingBoxes.Count() / prediction.PredictedLabels.Count());
    
  6. Ardından, tahmin için kullanılan görüntülerin özgün genişliğini ve yüksekliğini yakalayın.

    var originalWidth = testImage.Width;
    var originalHeight = testImage.Height;
    
  7. Kutuları çizmek için resmin neresinde olduğunu hesaplayın. Bunun için sınırlayıcı kutu öbeklerinin sayısını temel alan bir for döngü oluşturun.

    for (int i = 0; i < boundingBoxes.Count(); i++)
    {
    }
    
  8. Döngü içinde for , x ve y koordinatlarının konumunun yanı sıra görüntü üzerinde çizilmek üzere kutunun genişliğini ve yüksekliğini hesaplayın. Yapmanız gereken ilk şey, ElementAt yöntemini kullanarak sınırlayıcı kutular kümesini elde etmektir.

    var boundingBox = boundingBoxes.ElementAt(i);
    
  9. Geçerli sınırlayıcı kutuyla, artık kutunun çizileceği yeri hesaplayabilirsiniz. Sınırlayıcı kutunun ilk ve üçüncü öğeleri için özgün görüntü genişliğini, ikinci ve dördüncü öğeler için de özgün görüntü yüksekliğini kullanın.

    var left = boundingBox[0] * originalWidth;
    var top = boundingBox[1] * originalHeight;
    var right = boundingBox[2] * originalWidth;
    var bottom = boundingBox[3] * originalHeight;
    
  10. Görüntünün içinde algılanan nesnenin çevresinde çizim yapmak için kutunun genişliğini ve yüksekliğini hesaplayın. X ve y öğeleri, önceki hesaplamadaki left ve top değişkenleridir. Math.Abs Negatif olması durumunda genişlik ve yükseklik hesaplamalarından mutlak değeri almak için yöntemini kullanın.

    var x = left;
    var y = top;
    var width = Math.Abs(right - left);
    var height = Math.Abs(top - bottom);
    
  11. Ardından, etiket dizisinden tahmin edilen etiketi alın.

    var label = labels[prediction.PredictedLabels[i]];
    
  12. yöntemini kullanarak Graphics.FromImage test görüntüsünü temel alan bir grafik oluşturun.

    using var graphics = Graphics.FromImage(testImage);
    
  13. Sınırlayıcı kutu bilgilerini kullanarak görüntü üzerinde çizim yapın. İlk olarak, dikdörtgenin rengini ve genişliğini belirlemek için bir DrawRectangle nesnesi alan Pen yöntemini kullanarak algılanan nesnelerin çevresine dikdörtgen çizin ve x, y, width ve height değişkenlerini geçirin.

    graphics.DrawRectangle(new Pen(Color.NavajoWhite, 8), x, y, width, height);
    
  14. Ardından, yazdırılacak dizgiyi alan bir DrawString yöntemi ve dizgiyi nasıl çizeceğinizi ve nereye yerleştireceğinizi belirleyecek bir Font nesnesiyle kutunun içinde tahmin edilen etiketi görüntüleyin.

    graphics.DrawString(label, new Font(FontFamily.Families[0], 18f), Brushes.NavajoWhite, x + 5, y + 5);
    
  15. Döngüden for sonra, tahmin edilen dosyanın zaten var olup olmadığını denetleyin. Varsa silin. Ardından, bunu tanımlı çıkış yoluna kaydedin.

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

Sonraki Adımlar

Diğer görüntü sınıflandırma öğreticilerinden birini deneyin: