Все более и более распространенной становится возможность сделать фотографию и распознать ее содержимое. Мы можем наблюдать это в наших банковских приложениях при внесении мобильного депозита, в приложениях для фото при добавлении фильтров и в приложениях HotDog, чтобы определить, является ли наша еда хот-догом.
Благодаря сервису Azure Custom Vision нам не нужно изучать сложные алгоритмы машинного обучения для реализации классификации изображений.
В этой статье мы рассмотрим, как реализовать классификацию изображений с помощью сервиса Azure Custom Vision, TensorFlow Lite (платформа машинного обучения с открытым исходным кодом) и Xamarin.Android. Примечание: Для Xamarin.iOS мы также можем использовать сервис Azure Custom Vision с CoreML, но лучше прибережем это для другой статьи.
Библиотеки классификации изображений
Мы будем использовать сервис Azure Custom Vision и TensorFlow Lite для реализации нашей классификации изображений.
1. Сервис Azure Custom Vision
Сервис Azure Custom Vision упрощает создание и обучение модели машинного обучения — для этого не требуется опыт работы с Artificail Intelligence (AI) или Machine Learning (ML). Используя веб-портал сервиса Custom Vision, мы можем сделать следующее без написания какого-либо кода AI/ML:
- Загрузить обучающее изображение
- Отметить Теги/Метки объекта(ов) на изображении
- Повторить (модель становится лучше с большим количеством обучающих данных)
- Вот и все — сервис Custom Vision позаботится обо всем остальном!
2. TensorFlow Lite
TensorFlow Lite — это платформа машинного обучения с открытым исходным кодом, которая позволяет нам использовать TensorFlow в IoT и мобильных устройствах. TensorFlow Lite и TensorFlow доступны в open-source на GitHub.
Реализация классификации изображений с помощью Azure + Xamarin.Android
Полностью готовый образец приложения для классификации изображений доступен на GitHub.
1. Обучение модели
Используя веб-портал сервиса Custom Vision, мы сначала обучим модели классификации изображений. 1. На веб-портале сервиса Custom Vision нажмите New Project
2. В окне Create new project выставьте следующие параметры:- Name: XamarinImageClassification
- Description: Identify Objects in Images
- Resource: [Create a new resource]
- Project Type: Classification
- Classification Types: Multilabel (Multiple tags per image)
- Domains: General (compact)
- Export Capabilities: Basic platforms
3. В окне Create new project нажмите Create project
4. В окне XamarinImageClassification нажмите Add images
5. Выберите изображения, содержащие объект для идентификации
6. В окне Image Upload добавьте тег
Примечание: в данном примере мы работаем с изображениями грибов
7. В окне Image upload нажмите Upload
Примечание: продолжайте загружать изображения, пока у вас не будет, по крайней мере, 5 изображений для каждого тега
8. В окне XamarinImageClassification в правом верхнем углу окна нажмите кнопку Train Model (зеленое изображение шестеренок)
9. В окне Choose Training Type выберите Quick Training
10. В окне Choose Training Type выберите Train
2. Экспорт обученной модели из сервиса Azure Custom Vision
Теперь, когда мы обучили нашу модель, давайте экспортируем ее для использования в нашем мобильном приложении. Это позволит нам использовать модель без подключения к интернету, что обеспечит наилучшую конфиденциальность пользователя, потому что его фотографии никогда не покинут мобильное устройство.
Чтобы экспортировать нашу модель, давайте сделаем следующее:
1. В окне XamarinImageClassifcation в верхней части страницы выберите вкладку Performance
2. На вкладке Performace нажмите кнопку Export (стрелка, направленная вниз)
3. В окне Choose your platform выберите TensorFlow
5. В окне Choose your platform выберите Download
3. Импорт TensorFlow Lite в наше приложение Xamarin.Android
1. Установите соответствующий пакет NuGet в нашем проекте Xamarin.Android Примечание: Этот пакет NuGet представляет собой проект с открытым исходным кодом, созданный командой Xamarin в Microsoft. Он содержит привязки C# для оригинальной библиотеки TensorFlow Lite, позволяющие использовать ее в нашем приложении Xamarin.Android 2. Распакуйте экспортированную модель, которую мы загрузили с веб-портала сервиса Custom Vision Примечание: внутри zip-файла находятся labels.txt и model.tflite:
- labels.txt содержит теги изображений, созданные во время подготовки к обучению на сайте Custom Vision
- models.tflite является моделью машинного обучения, которую мы используем для наших прогнозов.
3. В Visual Studio, в проекте Xamarin.Android, щелкните правой кнопкой мыши папку Assets
4. Во всплывшем меню выберите пункт Add ? Existing Item…
5. В меню Add Existing Item выберите оба недавно распакованных файла:
- models.tflite
- labels.txt
6. В Visual Studio, в Xamarin.Android ? Assets, щелкните правой кнопкой мыши на labels.txt
7. Во всплывшем меню выберите Properties
8. В окне Properties выберите Build Action ? Android Asset
9. В Visual Studio, в Xamarin.Android ? Assets, щелкните правой кнопкой мыши на models.tflite
10. Во всплывшем меню выберите Properties
11. В окне Properties выберите Build Action ? Android Asset
4. Внедрение кода классификации изображений для Xamarin.Android
Теперь, когда мы импортировали модель, пришло время заняться написанием кода.
Напоминаю, полностью готовый образец приложения для классификации изображений доступен на GitHub. В проекте Xamarin.Android, добавьте ImageClassifcationModel.cs и TensorflowClassifier.cs:
ImageClassificationModel.cs
public class ImageClassificationModel { public ImageClassificationModel(string tagName, float probability) { TagName = tagName; Probability = probability; } public float Probability { get; } public string TagName { get; } }
TensorflowClassifier.cs
using System.Collections.Generic; using System.IO; using System.Linq; using Android.App; using Android.Graphics; using Java.IO; using Java.Nio; using Java.Nio.Channels; public class TensorflowClassifier { //FloatSize является константой со значением 4, потому что значение с плавающей запятой составляет 4 байта const int FloatSize = 4; //PixelSize - это константа со значением 3, потому что у пикселя есть три цветовых канала: красный, зеленый и синий. const int PixelSize = 3; public List<ImageClassificationModel> Classify(byte[] image) { var mappedByteBuffer = GetModelAsMappedByteBuffer(); var interpreter = new Xamarin.TensorFlow.Lite.Interpreter(mappedByteBuffer); //Чтобы изменить размер изображения, сначала нужно получить необходимую ширину и высоту var tensor = interpreter.GetInputTensor(0); var shape = tensor.Shape(); var width = shape[1]; var height = shape[2]; var byteBuffer = GetPhotoAsByteBuffer(image, width, height); //Используйте StreamReader для инпорта из labels.txt var streamReader = new StreamReader(Application.Context.Assets.Open("labels.txt")); //Преобразуйте labels.txt в List<string> var labels = streamReader.ReadToEnd().Split(' ').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToList(); //Преобразуйте наш двумерный массив в Java.Lang.Object, обязательный ввод для Xamarin.TensorFlow.List.Interpreter. var outputLocations = new float[1][] { new float[labels.Count] }; var outputs = Java.Lang.Object.FromArray(outputLocations); interpreter.Run(byteBuffer, outputs); var classificationResult = outputs.ToArray<float[]>(); //Сопоставьте classificationResult с метками и отсортируйте результат, чтобы определить, какая метка имеет наибольшую вероятность var classificationModelList = new List<ImageClassificationModel>(); for (var i = 0; i < labels.Count; i++) { var label = labels[i]; classificationModelList.Add(new ImageClassificationModel(label, classificationResult[0][i])); } return classificationModelList; } //Преобразуйте model.tflite в Java.Nio.MappedByteBuffer, требуемый тип для Xamarin.TensorFlow.Lite.Interpreter. private MappedByteBuffer GetModelAsMappedByteBuffer() { var assetDescriptor = Application.Context.Assets.OpenFd("model.tflite"); var inputStream = new FileInputStream(assetDescriptor.FileDescriptor); var mappedByteBuffer = inputStream.Channel.Map(FileChannel.MapMode.ReadOnly, assetDescriptor.StartOffset, assetDescriptor.DeclaredLength); return mappedByteBuffer; } //Изменить размер изображения для интерпретатора TensorFlow private ByteBuffer GetPhotoAsByteBuffer(byte[] image, int width, int height) { var bitmap = BitmapFactory.DecodeByteArray(image, 0, image.Length); var resizedBitmap = Bitmap.CreateScaledBitmap(bitmap, width, height, true); var modelInputSize = FloatSize * height * width * PixelSize; var byteBuffer = ByteBuffer.AllocateDirect(modelInputSize); byteBuffer.Order(ByteOrder.NativeOrder()); var pixels = new int[width * height]; resizedBitmap.GetPixels(pixels, 0, resizedBitmap.Width, 0, 0, resizedBitmap.Width, resizedBitmap.Height); var pixel = 0; //Прокрутите каждый пиксель для создания Java.Nio.ByteBuffer for (var i = 0; i < width; i++) { for (var j = 0; j < height; j++) { var pixelVal = pixels[pixel++]; byteBuffer.PutFloat(pixelVal >> 16 & 0xFF); byteBuffer.PutFloat(pixelVal >> 8 & 0xFF); byteBuffer.PutFloat(pixelVal & 0xFF); } } bitmap.Recycle(); return byteBuffer; } }
Вот и все! Теперь мы можем передать изображение в TensorflowClassifier.Classify, чтобы получить ImageClassificationModel.
Материалы для дополнительного изучения
Ознакомьтесь со ссылками ниже: