Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Узнайте, как использовать ML.NET для обнаружения объектов в изображениях с помощью модели ONNX, обученной в службе Пользовательского визуального распознавания Майкрософт.
Служба Пользовательского визуального распознавания Майкрософт — это служба искусственного интеллекта, которая обучает модель на основе отправленных изображений. Затем можно экспортировать модель в формат ONNX и использовать ее в ML.NET для прогнозирования.
В этом руководстве вы узнаете, как:
- Создание модели ONNX с помощью службы пользовательского визуального распознавания
- Включение модели ONNX в конвейер ML.NET
- Обучение модели ML.NET
- Обнаружение признаков остановки в тестовых образах
Предпосылки
- Visual Studio 2022 или более поздней версии.
- Скачайте набор данных из 50 образов стоп-подписей.
- Учетная запись Azure. Если у вас нет учетной записи Azure, создайте бесплатную учетную запись Azure.
Создание модели
Создание проекта в службе "Пользовательское визуальное распознавание"
Войдите в службу Пользовательского визуального распознавания Майкрософт и выберите новый проект.
В диалоговом окне "Новый проект" заполните следующие обязательные элементы:
- Задайте имя проекта пользовательского визуального распознавания как StopSignDetection.
- Выберите ресурс , который вы будете использовать. Это ресурс Azure, который будет создан для проекта Пользовательского визуального распознавания. Если нет в списке, его можно создать, выбрав ссылку "Создать новую ".
- Задайте тип проекта как обнаружение объектов.
- Задайте типы классификации как мультикласс , так как на изображение будет один класс.
- Задайте домен как общий (компактный) [S1]. Компактный домен позволяет скачать модель ONNX.
- Для возможностей экспорта выберите базовые платформы, чтобы разрешить экспорт модели ONNX.
После заполнения указанных выше полей нажмите кнопку "Создать проект".
Добавление изображений
- После создания проекта нажмите кнопку "Добавить изображения ", чтобы начать добавление изображений для модели для обучения. Выберите загруженные изображения дорожных знаков 'Стоп'.
- Выберите первое изображение, которое отображается. Вы можете выбрать объекты на изображении, которое требуется обнаружить модели. Выберите знак остановки на изображении. Всплывающее окно отображает и задает тег как знак остановки.
- Повторите действие для всех оставшихся изображений. Некоторые изображения имеют более одного знака остановки, поэтому обязательно пометьте все, что находятся в изображениях.
Обучение модели
После загрузки и маркировки изображений модель можно обучить. Выберите "Обучение".
Появляется всплывающее окно с вопросом, какой тип обучения использовать. Выберите быстрое обучение и нажмите кнопку "Обучение".
Скачивание модели ONNX
После завершения обучения нажмите кнопку "Экспорт ". При отображении всплывающего окна выберите ONNX, чтобы скачать модель ONNX .
Проверка модели ONNX
Распакуйте скачанный ONNX-файл. Папка содержит несколько файлов, но они используются в этом руководстве:
- labels.txt, который представляет собой текстовый файл, содержащий метки, определенные в службе пользовательского визуального распознавания.
- model.onnx, которая является моделью ONNX, которая будет использоваться для прогнозирования в ML.NET.
Чтобы создать конвейер ML.NET, вам потребуется имена входных и выходных столбцов. Чтобы получить эти сведения, используйте Netron, веб-приложение и классическое приложение, которое может анализировать модели ONNX и показывать их архитектуру.
При использовании веб-приложения или классического приложения Netron откройте модель ONNX в приложении. После открытия отображается граф. На этом графе показано, что вам потребуется создать конвейер ML.NET для прогнозирования.
Имя входного столбца — имя входного столбца , необходимое при применении модели ONNX в ML.NET.
Имя выходного столбца — имя выходного столбца , необходимое при применении модели ONNX в ML.NET.
Размер изображения — размер, необходимый при изменении размера изображений в конвейере ML.NET.
Создание консольного проекта C#
В Visual Studio создайте консольное приложение C# с именем StopSignDetection. Выберите .NET 8 в качестве целевой платформы.
Установите следующие пакеты NuGet для проекта:
- Microsoft.ML
- Microsoft.ML.ImageAnalytics
- Microsoft.Onnx.Transformer
Замечание
В этом примере используется последняя стабильная версия упомянутых пакетов NuGet, если не указано иное.
Ссылка на модель ONNX
Найдите два файла из модели ONNX (labels.txt и model.onnx) в обозревателе решений Visual Studio. Щелкните их правой кнопкой мыши, и в окне "Свойства" установите параметр Копировать в выходной каталог на значение Копировать при изменении.
Создание входных и прогнозирующих классов
Добавьте новый класс в проект и назовите его
StopSignInput. Затем добавьте в класс следующую структуру:public struct ImageSettings { public const int imageHeight = 320; public const int imageWidth = 320; }Затем добавьте в класс следующее свойство.
public class StopSignInput { [ImageType(ImageSettings.imageHeight, ImageSettings.imageWidth)] public Bitmap Image { get; set; } }Свойство
Imageсодержит растровое изображение изображения, используемого для прогнозирования. АтрибутImageTypeсообщает ML.NET, что свойство является изображением с размерами 320 на 320, определённое с помощью Netron.Добавьте в проект другой класс и назовите его
StopSignPrediction. Затем добавьте в класс следующие свойства.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; } }Свойство
PredictedLabelsсодержит прогнозы меток для каждого обнаруженного объекта. Тип - это массив типа float, поэтому каждый элемент в массиве является предсказанием для каждой метки. АтрибутColumnNameсообщает ML.NET, что этот столбец в модели является именем, указанным какdetected_classes.Свойство
BoundingBoxesсодержит ограничивающие прямоугольники для каждого обнаруженного объекта. Тип представляет собой массив чисел с плавающей запятой, и каждый обнаруженный объект содержит четыре элемента в массиве для ограничивающей рамки. АтрибутColumnNameсообщает ML.NET, что этот столбец в модели является именем, указанным какdetected_boxes.Свойство
Scoresсодержит оценки достоверности каждого прогнозируемого объекта и его метки. Тип представляет собой массив с плавающей запятой, поэтому каждый элемент в массиве — это оценка достоверности каждой метки. АтрибутColumnNameсообщает ML.NET, что этот столбец в модели является указанным именем.detected_scores
Использование модели для прогнозирования
Добавьте директивы using.
В файле Program.cs добавьте следующие using директивы в начало файла.
using Microsoft.ML;
using Microsoft.ML.Transforms.Image;
using System.Drawing;
using WeatherRecognition;
Создание объектов
MLContextСоздайте объект.var context = new MLContext();Создайте новый пустой
IDataViewStopSignInputсписок.var data = context.Data.LoadFromEnumerable(new List<StopSignInput>());Для согласованности сохраните прогнозируемые образы в пути сборки.
var root = new FileInfo(typeof(Program).Assembly.Location); var assemblyFolderPath = root.Directory.FullName;
Создание конвейера
С помощью пустого IDataView созданного конвейера можно создать для прогнозирования любых новых образов. Конвейер состоит из нескольких шагов:
Измените размер входящих изображений.
Изображение, отправляемое в модель для прогнозирования, часто будет в другом пропорциональном отношении к изображениям, которые были использованы для обучения модели. Чтобы обеспечить согласованность изображения для точных прогнозов, измените размер изображения на 320x320. Для этого используйте
ResizeImagesметод и задайтеimageColumnNameимяStopSignInput.Imageсвойства.var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: "image_tensor", imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight, inputColumnName: nameof(StopSignInput.Image))Извлеките пиксели изображения.
После изменения размера изображения необходимо извлечь пиксели изображения. Добавьте метод в
ExtractPixelsконвейер и укажите имя столбца, чтобы вывести пиксели на использованиеoutputColumnNameпараметра..Append(context.Transforms.ExtractPixels(outputColumnName: "image_tensor"))Примените модель ONNX к изображению, чтобы сделать прогноз. Для этого требуется несколько параметров:
- modelFile — путь к файлу модели ONNX
- outputColumnNames — массив строк, содержащий имена всех имен выходных столбцов, которые можно найти при анализе модели ONNX в Netron.
- inputColumnNames — строковый массив, содержащий имена всех входных столбцов, которые также можно найти при анализе модели ONNX в Netron.
.Append(context.Transforms.ApplyOnnxModel(outputColumnNames: new string[] { "detected_boxes", "detected_scores", "detected_classes" }, inputColumnNames: new string[] { "image_tensor" }, modelFile: "./Model/model.onnx"));
Соответствие модели
Теперь, когда вы определили конвейер, его можно использовать для сборки модели ML.NET.
Fit Используйте метод в конвейере и передайте пустоеIDataView.
var model = pipeline.Fit(data);
Затем, чтобы сделать прогнозы, используйте модель для создания подсистемы прогнозирования. Это универсальный метод, поэтому он принимает классы StopSignInput и StopSignPrediction, которые были созданы ранее.
var predictionEngine = context.Model.CreatePredictionEngine<StopSignInput, StopSignPrediction>(model);
Извлечение меток
Чтобы сопоставить выходные данные модели с метками, необходимо извлечь метки, предоставляемые Custom Vision. Эти метки находятся в labels.txt файле, который был включен в ZIP-файл с моделью ONNX.
ReadAllLines Вызовите метод для чтения всех меток в файле.
var labels = File.ReadAllLines("./model/labels.txt");
Прогнозирование на тестовом изображении
Теперь модель можно использовать для прогнозирования на новых изображениях. В проекте есть тестовая папка, которую можно использовать для прогнозирования. Эта папка содержит два случайных изображения со знаком остановки на нём из Unsplash. Один образ имеет один знак остановки, а другой имеет два знака остановки.
GetFiles Используйте метод для чтения путей к файлам изображений в каталоге.
var testFiles = Directory.GetFiles("./test");
Прокрутите пути к файлам, чтобы сделать прогноз с помощью модели и вывести результат.
foreachСоздайте цикл для циклического прохождения тестовых образов.Bitmap testImage; foreach (var image in testFiles) { }В цикле
foreachсоздайте прогнозируемое имя образа на основе имени исходного тестового образа.var predictedImage = $"{Path.GetFileName(image)}-predicted.jpg";Кроме того, в цикле
foreachсоздайтеFileStreamизображения и преобразуйте его вBitmap.using (var stream = new FileStream(image, FileMode.Open)) { testImage = (Bitmap)Image.FromStream(stream); }Кроме того, в цикле
foreachвызовитеPredictметод в подсистеме прогнозирования.var prediction = predictionEngine.Predict(new StopSignInput { Image = testImage });С помощью прогноза можно получить ограничивающие прямоугольники. Chunk Используйте метод, чтобы определить, сколько объектов обнаружена модель. Это можно сделать, приняв количество прогнозируемых ограничивающих прямоугольников и разделив это значение на число прогнозируемых меток. Например, если в изображении обнаружены три объекта, в
BoundingBoxesмассиве было бы 12 элементов, а прогнозируются три метки. ЗатемChunkметод даст вам три массива из четырех, чтобы представлять ограничивающие прямоугольники для каждого объекта.var boundingBoxes = prediction.BoundingBoxes.Chunk(prediction.BoundingBoxes.Count() / prediction.PredictedLabels.Count());Затем зафиксировать исходную ширину и высоту изображений, используемых для прогнозирования.
var originalWidth = testImage.Width; var originalHeight = testImage.Height;Вычислите, где на изображении нужно нарисовать коробки. Для этого создайте
forцикл на основе количества ограничивающих прямоугольников.for (int i = 0; i < boundingBoxes.Count(); i++) { }forВ цикле вычислите положение координат x и y, а также ширину и высоту поля, нарисуемого на изображении. Первое, что необходимо сделать, — это получить набор ограничивающих прямоугольников с помощью методаElementAt.var boundingBox = boundingBoxes.ElementAt(i);С помощью текущего ограничивающего прямоугольника теперь можно вычислить место для рисования поля. Используйте исходные размеры изображения: ширину для первых и третьих элементов ограничительной рамки и высоту для второго и четвертого элементов.
var left = boundingBox[0] * originalWidth; var top = boundingBox[1] * originalHeight; var right = boundingBox[2] * originalWidth; var bottom = boundingBox[3] * originalHeight;Вычислите ширину и высоту поля для рисования вокруг обнаруженного объекта в изображении. Элементы x и y — это
lefttopпеременные из предыдущего вычисления.Math.AbsИспользуйте метод, чтобы получить абсолютное значение от вычислений ширины и высоты, если это отрицательно.var x = left; var y = top; var width = Math.Abs(right - left); var height = Math.Abs(top - bottom);Затем получите предсказанную метку из массива меток.
var label = labels[prediction.PredictedLabels[i]];Создайте рисунок на основе тестового
Graphics.FromImageобраза с помощью метода.using var graphics = Graphics.FromImage(testImage);Нарисуйте изображение с помощью сведений об ограничивающем поле. Во-первых, нарисуйте прямоугольник вокруг обнаруженных объектов, используя метод
DrawRectangle, который принимает объектPen, чтобы определить цвет и ширину прямоугольника, и передайте в него переменныеx,y,widthиheight.graphics.DrawRectangle(new Pen(Color.NavajoWhite, 8), x, y, width, height);Затем покажите прогнозируемую метку внутри рамки с помощью метода
DrawString, который принимает строку для печати и объектFont, чтобы определить, как нарисовать строку и где её разместить.graphics.DrawString(label, new Font(FontFamily.Families[0], 18f), Brushes.NavajoWhite, x + 5, y + 5);После цикла проверьте, существует ли прогнозируемый
forфайл. Если да, удалите это. Затем сохраните его в определенный выходной путь.if (File.Exists(predictedImage)) { File.Delete(predictedImage); } testImage.Save(Path.Combine(assemblyFolderPath, predictedImage));
Дальнейшие шаги
Ознакомьтесь с одним из других руководств по классификации изображений: