Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Pelajari cara menggunakan ML.NET untuk mendeteksi objek dalam gambar menggunakan model ONNX yang dilatih dalam layanan Microsoft Custom Vision.
Layanan Microsoft Custom Vision adalah layanan AI yang melatih model berdasarkan gambar yang Anda unggah. Anda kemudian dapat mengekspor model ke format ONNX dan menggunakannya dalam ML.NET untuk membuat prediksi.
Dalam tutorial ini, Anda akan belajar cara:
- Menggunakan layanan Custom Vision untuk membuat model ONNX
- Menggabungkan model ONNX ke dalam alur ML.NET
- Melatih model ML.NET
- Mendeteksi tanda berhenti dalam gambar pengujian
Prasyarat
- Visual Studio 2022 atau yang lebih baru.
- Unduh himpunan data 50 gambar rambu berhenti.
- Akun Azure. Jika Anda tidak memilikinya, buat akun Azure gratis.
Buatlah model
Membuat proyek Custom Vision
Masuk ke layanan Microsoft Custom Vision dan pilih Proyek Baru.
Dalam dialog Proyek Baru , isi item yang diperlukan berikut ini:
- Atur Nama proyek Custom Vision sebagai StopSignDetection.
- Pilih Sumber Daya yang akan Anda gunakan. Ini adalah sumber daya Azure yang akan dibuat untuk proyek Custom Vision. Jika tidak ada yang terdaftar, dapat dibuat dengan memilih tautan Buat baru.
- Atur Jenis proyek sebagai Deteksi Objek.
- Atur Jenis Klasifikasi sebagai Multikelas karena akan ada satu kelas per gambar.
- Atur Domain sebagai Umum (ringkas) [S1]. Domain ringkas memungkinkan Anda mengunduh model ONNX.
- Untuk Kemampuan ekspor, pilih Platform dasar untuk memungkinkan ekspor model ONNX.
Setelah bidang di atas diisi, pilih Buat proyek.
Menambahkan gambar
- Dengan proyek yang dibuat, pilih Tambahkan gambar untuk mulai menambahkan gambar agar model dapat dilatih. Pilih gambar stop-sign yang Anda unduh.
- Pilih gambar pertama yang ditampilkan. Anda dapat memilih objek dalam gambar yang Anda inginkan untuk dideteksi model. Pilih rambu berhenti dalam gambar. Popup menampilkan dan mengatur tag sebagai stop-sign.
- Ulangi untuk semua gambar yang tersisa. Beberapa gambar memiliki lebih dari satu tanda berhenti, jadi pastikan untuk menandai semua yang ada dalam gambar.
Melatih model
Dengan gambar yang diunggah dan ditandai, model sekarang dapat dilatih. Pilih Train.
Popup muncul menanyakan jenis pelatihan apa yang akan digunakan. Pilih Pelatihan cepat lalu pilih Latih.
Mengunduh model ONNX
Setelah pelatihan selesai, klik tombol Ekspor . Saat popup ditampilkan, pilih ONNX untuk mengunduh model ONNX.
Memeriksa model ONNX
Unzip file ONNX yang diunduh. Folder berisi beberapa file, tetapi dua yang akan Anda gunakan dalam tutorial ini adalah:
- labels.txt, yang merupakan file teks yang berisi label yang ditentukan dalam layanan Custom Vision.
- model.onnx, yang merupakan model ONNX yang akan Anda gunakan untuk membuat prediksi dalam ML.NET.
Untuk membangun alur ML.NET, Anda memerlukan nama nama kolom input dan output. Untuk mendapatkan informasi ini, gunakan Netron, aplikasi web dan desktop yang dapat menganalisis model ONNX dan menampilkan arsitekturnya.
Saat menggunakan aplikasi web atau desktop Netron, buka model ONNX di aplikasi. Setelah terbuka, grafik akan ditampilkan. Grafik ini memberi tahu Anda beberapa hal yang perlu Anda buat alur ML.NET untuk prediksi.
Nama kolom input - Nama kolom input diperlukan saat menerapkan model ONNX di ML.NET.
Nama kolom output - Nama kolom output yang diperlukan saat menerapkan model ONNX di ML.NET.
Ukuran gambar - Ukuran yang diperlukan saat mengubah ukuran gambar dalam alur ML.NET.
Membuat proyek konsol C#
Di Visual Studio, buat Aplikasi Konsol C# yang disebut "StopSignDetection". Pilih .NET 8 sebagai kerangka kerja target.
Instal paket NuGet berikut untuk proyek:
- Microsoft.ML
- Microsoft.ML.ImageAnalytics
- Microsoft.Onnx.Transformer
Nota
Sampel ini menggunakan versi stabil terbaru dari paket NuGet yang disebutkan kecuali dinyatakan lain.
Mereferensikan model ONNX
Temukan dua file dari model ONNX (labels.txt dan model.onnx) di Penjelajah Solusi Visual Studio. Klik kanan mereka dan, di jendela Properti, atur Salin ke direktori output ke Salin jika lebih baru.
Membuat kelas input dan prediksi
Tambahkan kelas baru ke proyek Anda dan beri nama
StopSignInput. Kemudian, tambahkan struktur berikut ke kelas :public struct ImageSettings { public const int imageHeight = 320; public const int imageWidth = 320; }Selanjutnya, tambahkan properti berikut ke kelas .
public class StopSignInput { [ImageType(ImageSettings.imageHeight, ImageSettings.imageWidth)] public Bitmap Image { get; set; } }Properti
Imageberisi bitmap gambar yang digunakan untuk prediksi. AtributImageTypemenginformasikan ML.NET bahwa properti adalah gambar dengan dimensi 320 kali 320, yang ditentukan menggunakan Netron.Tambahkan kelas lain ke proyek Anda dan beri nama
StopSignPrediction. Kemudian, tambahkan properti berikut ke kelas .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; } }Properti
PredictedLabelsberisi prediksi label untuk setiap objek yang terdeteksi. Jenisnya adalah array float, sehingga setiap item dalam array adalah prediksi setiap label. AtributColumnNamememberi tahu ML.NET bahwa kolom ini dalam model adalah nama yang diberikan, yaitudetected_classes.Properti
BoundingBoxesberisi kotak pembatas (bounding boxes) untuk setiap objek yang terdeteksi. Jenisnya adalah array float dan setiap objek yang terdeteksi memiliki empat item dalam array yang berfungsi sebagai kotak pembatas. AtributColumnNamememberi tahu ML.NET bahwa kolom ini dalam model adalah nama yang diberikan, yaitudetected_boxes.Properti
Scoresberisi skor keyakinan dari setiap objek yang diprediksi dan labelnya. Tipe datanya adalah array float, sehingga setiap item dalam array adalah skor kepercayaan dari setiap label. AtributColumnNamememberi tahu ML.NET bahwa kolom ini dalam model adalah nama yang diberikan, yaitudetected_scores.
Menggunakan model untuk membuat prediksi
Tambahkan direktif penggunaan
Dalam file Program.cs , tambahkan arahan berikut using ke bagian atas file.
using Microsoft.ML;
using Microsoft.ML.Transforms.Image;
using System.Drawing;
using WeatherRecognition;
Membuat objek
MLContextBuat objek.var context = new MLContext();IDataViewBuat dengan daftar kosongStopSignInputbaru.var data = context.Data.LoadFromEnumerable(new List<StopSignInput>());Untuk konsistensi, simpan gambar yang diprediksi ke jalur perakitan.
var root = new FileInfo(typeof(Program).Assembly.Location); var assemblyFolderPath = root.Directory.FullName;
Membangun alur
Setelah elemen kosong IDataView dibuat, pipeline dapat dibangun untuk memprediksi gambar baru apa pun. Alur terdiri dari beberapa langkah:
Mengubah ukuran gambar masuk.
Gambar yang dikirim ke model untuk prediksi akan sering berada dalam rasio aspek yang berbeda dengan gambar yang dilatih pada model. Agar gambar tetap konsisten untuk prediksi yang akurat, mengubah ukuran gambar menjadi 320x320. Untuk melakukannya, gunakan
ResizeImagesmetode dan aturimageColumnNamesebagai namaStopSignInput.Imageproperti .var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: "image_tensor", imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight, inputColumnName: nameof(StopSignInput.Image))Ekstrak piksel gambar.
Setelah gambar diubah ukurannya, Anda perlu mengekstrak piksel dari gambar. Tambahkan metode
ExtractPixelske alur kerja Anda dan tentukan nama kolom untuk mengeluarkan piksel menggunakan parameteroutputColumnName..Append(context.Transforms.ExtractPixels(outputColumnName: "image_tensor"))Terapkan model ONNX ke gambar untuk membuat prediksi. Ini membutuhkan beberapa parameter:
- modelFile - Jalur ke file model ONNX
- outputColumnNames - Array string yang berisi nama semua nama kolom output, yang dapat ditemukan saat menganalisis model ONNX di Netron.
- inputColumnNames - Array string yang berisi nama semua nama kolom input, yang juga dapat ditemukan saat menganalisis model ONNX di Netron.
Important
Hanya terapkan model dari sumber tepercaya. Menerapkan model dari sumber yang tidak tepercaya adalah risiko keamanan.
.Append(context.Transforms.ApplyOnnxModel(outputColumnNames: new string[] { "detected_boxes", "detected_scores", "detected_classes" }, inputColumnNames: new string[] { "image_tensor" }, modelFile: "./Model/model.onnx"));
Paskan model
Setelah menentukan alur, Anda dapat menggunakannya untuk membangun model ML.NET.
Fit Gunakan metode pada alur dan teruskan dalam kosong IDataView.
var model = pipeline.Fit(data);
Selanjutnya, untuk membuat prediksi, gunakan model untuk membuat mesin prediksi. Ini adalah metode generik, jadi dibutuhkan di StopSignInput kelas dan StopSignPrediction yang dibuat sebelumnya.
var predictionEngine = context.Model.CreatePredictionEngine<StopSignInput, StopSignPrediction>(model);
Mengekstrak label
Untuk memetakan output model ke labelnya, Anda perlu mengekstrak label yang disediakan oleh Custom Vision. Label ini berada dalam file labels.txt yang disertakan dalam file zip dengan model ONNX.
ReadAllLines Panggil metode untuk membaca semua label dari file.
var labels = File.ReadAllLines("./model/labels.txt");
Memprediksi pada gambar pengujian
Sekarang Anda dapat menggunakan model untuk memprediksi gambar baru. Dalam proyek, ada folder pengujian yang dapat Anda gunakan untuk membuat prediksi. Folder ini berisi dua gambar acak dengan rambu berhenti di dalamnya dari Unsplash. Satu gambar memiliki tanda berhenti sementara yang lain memiliki dua tanda berhenti.
GetFiles Gunakan metode untuk membaca jalur file gambar di direktori.
var testFiles = Directory.GetFiles("./test");
Telusuri jalur file untuk membuat prediksi dengan model dan keluarkan hasilnya.
Buat perulangan
foreachuntuk mengulangi gambar pengujian.Bitmap testImage; foreach (var image in testFiles) { }Dalam perulangan
foreach, hasilkan nama gambar yang diprediksi berdasarkan nama gambar pengujian asli.var predictedImage = $"{Path.GetFileName(image)}-predicted.jpg";Dalam perulangan
foreachjuga, buatFileStreamdari gambar dan ubah menjadiBitmap.using (var stream = new FileStream(image, FileMode.Open)) { testImage = (Bitmap)Image.FromStream(stream); }Juga dalam perulangan
foreach, panggilPredictmetode pada mesin prediksi.var prediction = predictionEngine.Predict(new StopSignInput { Image = testImage });Dengan prediksi, Anda bisa mendapatkan kotak pembatas. Chunk Gunakan metode untuk menentukan berapa banyak objek yang telah terdeteksi oleh model. Lakukan ini dengan menghitung jumlah kotak pembatas yang diprediksi dan membaginya dengan jumlah label yang diprediksi. Misalnya, jika Anda memiliki tiga objek yang terdeteksi dalam gambar, akan ada 12 item dalam
BoundingBoxesarray dan tiga label yang diprediksi. Metode iniChunkkemudian akan memberi Anda tiga array, masing-masing terdiri dari empat elemen yang mewakili kotak pembatas untuk setiap objek.var boundingBoxes = prediction.BoundingBoxes.Chunk(prediction.BoundingBoxes.Count() / prediction.PredictedLabels.Count());Selanjutnya, ambil lebar dan tinggi asli gambar yang digunakan untuk prediksi.
var originalWidth = testImage.Width; var originalHeight = testImage.Height;Hitung di mana dalam gambar untuk menggambar kotak. Untuk itu, buat perulangan
forberdasarkan jumlah gugus kotak pembatas.for (int i = 0; i < boundingBoxes.Count(); i++) { }Dalam perulangan
for, hitung posisi koordinat x dan y serta lebar dan tinggi kotak untuk menggambar gambar. Hal pertama yang perlu Anda lakukan adalah mendapatkan set kotak pembatas menggunakan metodeElementAt.var boundingBox = boundingBoxes.ElementAt(i);Dengan kotak pembatas saat ini, Anda sekarang dapat menghitung posisi untuk menggambar kotak. Gunakan lebar gambar asli untuk elemen pertama dan ketiga dari kotak pembatas, dan tinggi gambar asli untuk elemen kedua dan keempat.
var left = boundingBox[0] * originalWidth; var top = boundingBox[1] * originalHeight; var right = boundingBox[2] * originalWidth; var bottom = boundingBox[3] * originalHeight;Hitung lebar dan tinggi kotak untuk menggambar di sekitar objek yang terdeteksi dalam gambar. Item x dan y adalah
leftvariabel dantopdari perhitungan sebelumnya.Math.AbsGunakan metode untuk mendapatkan nilai absolut dari perhitungan lebar dan tinggi jika negatif.var x = left; var y = top; var width = Math.Abs(right - left); var height = Math.Abs(top - bottom);Selanjutnya, dapatkan label yang diprediksi dari array label.
var label = labels[prediction.PredictedLabels[i]];Buat grafik berdasarkan gambar pengujian menggunakan
Graphics.FromImagemetode .using var graphics = Graphics.FromImage(testImage);Gambar gambar menggunakan informasi kotak pembatas. Pertama, gambar persegi panjang di sekitar objek yang terdeteksi menggunakan metode
DrawRectangleyang menerima objekPenuntuk menentukan warna dan lebar persegi panjang, dan oper variabelx,y,width, danheight.graphics.DrawRectangle(new Pen(Color.NavajoWhite, 8), x, y, width, height);Kemudian, tampilkan label yang diprediksi di dalam kotak menggunakan metode
DrawStringyang menerima string untuk dicetak dan objekFontuntuk menentukan cara menggambar string dan di mana menempatkannya.graphics.DrawString(label, new Font(FontFamily.Families[0], 18f), Brushes.NavajoWhite, x + 5, y + 5);Setelah perulangan
for, periksa apakah file yang diprediksi sudah ada. Jika ya, hapus. Kemudian, simpan ke jalur output yang ditentukan.if (File.Exists(predictedImage)) { File.Delete(predictedImage); } testImage.Save(Path.Combine(assemblyFolderPath, predictedImage));
Langkah selanjutnya
Coba salah satu tutorial klasifikasi gambar lainnya: