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.
Bu makale, bir görüntüdeki nesneleri sınıflandırmak ve her sınıflandırmanın güvenilirliğini görüntülemek için ONNX modeli kullanan bir WinUI uygulaması oluşturma işleminde size yol gösterir. Windows uygulamanızda yapay zeka ve makine öğrenmesi modellerini kullanma hakkında daha fazla bilgi için bkz. Windows'de yapay zekayı kullanmaya başlama. Bu kılavuz, donanım hızlandırmalı çıkarım için yürütme sağlayıcılarını otomatik olarak yönetmek üzere Windows ML kullanır.
Yapay zeka özelliklerini kullanırken şunları gözden geçirmenizi öneririz: Windows'ta Sorumlu Üretken Yapay Zeka Uygulamaları ve Özellikleri Geliştirme.
ONNX çalışma zamanı nedir?
ONNX Runtime, donanıma özgü kitaplıkları tümleştirmeye yönelik esnek bir arabirime sahip platformlar arası bir makine öğrenmesi model hızlandırıcısıdır. ONNX Runtime PyTorch, Tensorflow/Keras, TFLite, scikit-learnve diğer çerçevelerden modellerle kullanılabilir. Daha fazla bilgi için ONNX Runtimekonumundaki https://onnxruntime.ai/docs/ web sitesine bakın.
Bu örnek, paylaşılan ve kullanıcının donanımı için en iyi yürütme sağlayıcılarını dinamik olarak indiren ONNX Runtime'yi kullanır. Windows ML, donanım seçimini soyutlar; uygulamanız belirli yürütme sağlayıcılarını paketlemeden GPU, NPU veya CPU hızlandırmadan otomatik olarak yararlanır.
Önkoşullar
- Cihazınızda geliştirici modu etkinleştirilmiş olmalıdır. Daha fazla bilgi için bkz . Cihazınızı geliştirme için etkinleştirme.
- .NET masaüstü geliştirme iş yüküyle Visual Studio 2022 veya üzeri.
Yeni bir C# WinUI uygulaması oluşturma
Visual Studio'da yeni bir proje oluşturun. Yeni proje oluştur iletişim kutusunda, dil filtresini "C#" ve proje türü filtresini "winui" olarak ayarlayın, ardından Blank app, Packaged (WinUI3 in Desktop) şablonunu seçin. Yeni projeyi "ONNXWinUIExample" olarak adlandırın.
Nuget paketlerine referans ekleme
| Paket | Açıklama |
|---|---|
| Microsoft.WindowsAppSDK.ML | Windows ML çalışma zamanını ONNX Runtime ve otomatik yürütme sağlayıcısı yönetimiyle sağlar. |
| SixLabors.ImageSharp | Model girişi için görüntüleri işlemeye yönelik görüntü yardımcı programları sağlar. |
Bu kitaplıklardan API'lere erişmek için dosyanın üst kısmına aşağıdaki using yönergelerini ekleyin.
// MainWindow.xaml.cs
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using Microsoft.Windows.AI.MachineLearning;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
Modeli projenize ekleme
Çözüm Gezgini'nde projenize sağ tıklayın ve Yeni Klasör Ekle'yi> seçin. Yeni klasörü "model" olarak adlandırın. Bu örnekte, 'den https://github.com/onnx/models modelini kullanacağız. https://github.com/onnx/models/blob/main/validated/vision/classification/resnet/model/resnet50-v2-7.onnxkonumunda modelin depo görünümüne gidin. *Ham dosyayı indir düğmesine tıklayın. Bu dosyayı yeni oluşturduğunuz "model" dizinine kopyalayın.
Çözüm Gezgini'nde model dosyasına tıklayın ve Çıkış Dizinine Kopyala'yı "Daha Yeniyse Kopyala" olarak ayarlayın.
Basit bir kullanıcı arabirimi oluşturma
Bu örnekte, kullanıcının modelle değerlendirilecek bir görüntü seçmesine olanak sağlayan bir Düğme , seçili görüntüyü görüntülemek için bir Görüntü denetimi ve görüntüde modelin algılanan nesneleri listelemek için TextBlock ve her nesne sınıflandırmasının güvenilirliğini içeren basit bir kullanıcı arabirimi oluşturacağız.
<!--MainWindow.xaml-->
<Grid Padding="25" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="myButton" Click="myButton_Click" Grid.Column="0" VerticalAlignment="Top">Select photo</Button>
<Image x:Name="myImage" MaxWidth="300" Grid.Column="1" VerticalAlignment="Top"/>
<TextBlock x:Name="featuresTextBlock" Grid.Column="2" VerticalAlignment="Top"/>
</Grid>
Modeli başlatma
MainWindow.xaml.cs dosyasında, MainWindow sınıfının içinde, modeli başlatacak InitModel adlı bir yardımcı yöntemi oluşturun. Bu yöntem, kullanıcının donanımı için en iyi kullanılabilir yürütme sağlayıcılarını otomatik olarak indirmek ve kaydetmek için Windows ML kullanır.
ExecutionProviderCatalog, donanım algılamayı ve EP seçimini işler; gpu bağdaştırıcısını el ile seçmeniz gerekmez. Son olarak, model dosyasının yolu verilerek yeni bir InferenceSession başlatılır.
// MainWindow.xaml.cs
private InferenceSession _inferenceSession;
private string modelDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "model");
private async Task InitModelAsync()
{
if (_inferenceSession != null)
{
return;
}
// Use Windows ML to download and register the best execution providers
var catalog = ExecutionProviderCatalog.GetDefault();
if (catalog is not null)
{
await catalog.EnsureAndRegisterCertifiedAsync();
}
// Create the inference session — uses registered EPs automatically
_inferenceSession = new InferenceSession($@"{modelDir}\resnet50-v2-7.onnx");
}
Görüntü yükleme ve analiz etme
Kolaylık olması için, bu örnekte görüntüyü yükleme ve biçimlendirme, modeli çağırma ve sonuçları görüntüleme adımlarının tümü düğme tıklama işleyicisine yerleştirilir. İşleyicide zaman uyumsuz işlemleri çalıştırabilmemiz için varsayılan şablonda yer alan düğme tıklama işleyicisine zaman uyumsuz anahtar sözcüğünü eklediğimize dikkat edin.
// MainWindow.xaml.cs
private async void myButton_Click(object sender, RoutedEventArgs e)
{
...
}
Kullanıcının kullanıcı arabiriminde analiz etmek ve görüntülemek üzere bilgisayarından bir görüntü seçmesine izin vermek için FileOpenPicker kullanın.
FileOpenPicker fileOpenPicker = new()
{
ViewMode = PickerViewMode.Thumbnail,
FileTypeFilter = { ".jpg", ".jpeg", ".png", ".gif" },
};
InitializeWithWindow.Initialize(fileOpenPicker, WinRT.Interop.WindowNative.GetWindowHandle(this));
StorageFile file = await fileOpenPicker.PickSingleFileAsync();
if (file == null)
{
return;
}
// Display the image in the UI
var bitmap = new BitmapImage();
bitmap.SetSource(await file.OpenAsync(Windows.Storage.FileAccessMode.Read));
myImage.Source = bitmap;
Ardından girişi model tarafından desteklenen bir biçime getirmek için işlememiz gerekir. SixLabors.ImageSharp kitaplığı, görüntüyü 24 bit RGB biçiminde yüklemek ve görüntüyü 224x224 piksel olarak yeniden boyutlandırmak için kullanılır. Ardından piksel değerleri 255*[0,485, 0,456, 0,406] ortalaması ve 255*[0,229, 0,224, 0,225] standart sapması ile normalleştirilir. Modelin beklediği biçimin ayrıntıları, resnet modelinin github sayfasında bulunabilir.
using var fileStream = await file.OpenStreamForReadAsync();
IImageFormat format = SixLabors.ImageSharp.Image.DetectFormat(fileStream);
using Image<Rgb24> image = SixLabors.ImageSharp.Image.Load<Rgb24>(fileStream);
// Resize image
using Stream imageStream = new MemoryStream();
image.Mutate(x =>
{
x.Resize(new ResizeOptions
{
Size = new SixLabors.ImageSharp.Size(224, 224),
Mode = ResizeMode.Crop
});
});
image.Save(imageStream, format);
// Preprocess image
// We use DenseTensor for multi-dimensional access to populate the image data
var mean = new[] { 0.485f, 0.456f, 0.406f };
var stddev = new[] { 0.229f, 0.224f, 0.225f };
DenseTensor<float> processedImage = new(new[] { 1, 3, 224, 224 });
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
Span<Rgb24> pixelSpan = accessor.GetRowSpan(y);
for (int x = 0; x < accessor.Width; x++)
{
processedImage[0, 0, y, x] = ((pixelSpan[x].R / 255f) - mean[0]) / stddev[0];
processedImage[0, 1, y, x] = ((pixelSpan[x].G / 255f) - mean[1]) / stddev[1];
processedImage[0, 2, y, x] = ((pixelSpan[x].B / 255f) - mean[2]) / stddev[2];
}
}
});
Ardından, yönetilen görüntü veri dizisinin üzerinde Tensor türünde bir OrtValue oluşturarak girişleri ayarlayacağız.
// Setup inputs
// Pin tensor buffer and create a OrtValue with native tensor that makes use of
// DenseTensor buffer directly. This avoids extra data copy within OnnxRuntime.
// It will be unpinned on ortValue disposal
using var inputOrtValue = OrtValue.CreateTensorValueFromMemory(OrtMemoryInfo.DefaultInstance,
processedImage.Buffer, new long[] { 1, 3, 224, 224 });
var inputs = new Dictionary<string, OrtValue>
{
{ "data", inputOrtValue }
};
Daha sonra çıkarım oturumu henüz başlatılmadıysa InitModelAsync yardımcı yöntemini çağırın. Ardından modeli çalıştırmak ve sonuçları almak için Run yöntemini çağırın.
// Run inference
if (_inferenceSession == null)
{
await InitModelAsync();
}
using var runOptions = new RunOptions();
using IDisposableReadOnlyCollection<OrtValue> results = _inferenceSession.Run(runOptions, inputs, _inferenceSession.OutputNames);
Model sonuçları yerel bir tensor arabelleği olarak oluşturur. Aşağıdaki kod, çıkışı bir kayanlar dizisine dönüştürür. Değerlerin [0,1] aralığında ve toplamının 1 olması için softmax işlevi uygulanır.
// Postprocess output
// We copy results to array only to apply algorithms, otherwise data can be accessed directly
// from the native buffer via ReadOnlySpan<T> or Span<T>
var output = results[0].GetTensorDataAsSpan<float>().ToArray();
float sum = output.Sum(x => (float)Math.Exp(x));
IEnumerable<float> softmax = output.Select(x => (float)Math.Exp(x) / sum);
Çıkış dizisinin her bir değerinin indeksi, modelin eğitildiği bir etiketle eşleşir ve bu endeksteki değer, etiketin, giriş görüntüsünde algılanan bir nesneyi temsil ettiğine dair modelin güven düzeyidir. En yüksek güvenilirlik değerine sahip 10 sonucu seçiyoruz. Bu kod, sonraki adımda tanımlayacağımız bazı yardımcı nesneleri kullanır.
// Extract top 10
IEnumerable<Prediction> top10 = softmax.Select((x, i) => new Prediction { Label = LabelMap.Labels[i], Confidence = x })
.OrderByDescending(x => x.Confidence)
.Take(10);
// Print results
featuresTextBlock.Text = "Top 10 predictions for ResNet50 v2...\n";
featuresTextBlock.Text += "-------------------------------------\n";
foreach (var t in top10)
{
featuresTextBlock.Text += $"Label: {t.Label}, Confidence: {t.Confidence}\n";
}
} // End of myButton_Click
Yardımcı nesneleri bildirme
Prediction sınıfı yalnızca bir nesne etiketini güvenilirlik değeriyle ilişkilendirmek için basit bir yol sağlar. içinde MainPage.xaml.cs, bu sınıfı ONNXWinUIExample ad alanı bloğunun içine, ancak MainWindow sınıf tanımının dışına ekleyin.
internal class Prediction
{
public object Label { get; set; }
public float Confidence { get; set; }
}
Ardından, etiketlerin model tarafından döndürülen sonuçların dizinlerine eşlenmesi için modelin eğitildiği tüm nesne etiketlerini listeleyen LabelMap yardımcı sınıfını belirli bir sırada ekleyin. Etiket listesi burada tam olarak sunulmak için çok uzun. LabelMap sınıfının tamamını ONNXRuntime github deposundaki bir örnek kod dosyasından kopyalayıp ONNXWinUIExample ad alanı bloğuna yapıştırabilirsiniz.
public class LabelMap
{
public static readonly string[] Labels = new[] {
"tench",
"goldfish",
"great white shark",
...
"hen-of-the-woods",
"bolete",
"ear",
"toilet paper"};
Örneği çalıştırma
Projeyi derleyin ve çalıştırın. Fotoğraf seç düğmesine tıklayın ve analiz etmek için bir resim dosyası seçin. Modelin tanıyabileceği şeyleri görmek ve ilginç sonuçlara sahip olabilecek bir görüntü seçmek için LabelMap yardımcı sınıf tanımına bakabilirsiniz. Model başlatıldıktan sonra, ilk kez çalıştırıldığında ve modelin işlenmesi tamamlandıktan sonra görüntüde algılanan nesnelerin listesini ve her tahminin güvenilirlik değerini görmeniz gerekir.
Top 10 predictions for ResNet50 v2...
-------------------------------------
Label: lakeshore, Confidence: 0.91674984
Label: seashore, Confidence: 0.033412453
Label: promontory, Confidence: 0.008877817
Label: shoal, Confidence: 0.0046836217
Label: container ship, Confidence: 0.001940886
Label: Lakeland Terrier, Confidence: 0.0016400366
Label: maze, Confidence: 0.0012478716
Label: breakwater, Confidence: 0.0012336193
Label: ocean liner, Confidence: 0.0011933135
Label: pier, Confidence: 0.0011284945