图像分类使我们的Xamarin应用程序可以识别照片中的对象。拍照和识别其内容的能力越来越普遍。我们可以在银行应用程序中进行移动存款时,在照片应用程序中添加过滤器时以及在HotDog应用程序中观察到这一点,以确定我们的食物是否是热狗。借助Azure自定义视觉服务,我们无需学习复杂的机器学习算法即可实现图像分类。在本文中,我们将研究如何使用Azure Custom Vision服务,TensorFlow Lite(开源机器学习平台)以及Xamarin.Android。注意:对于Xamarin.iOS,我们还可以将Azure Custom Vision服务与CoreML结合使用,但最好将其保存在另一篇文章中。图像分类库
我们将使用Azure自定义视觉服务和TensorFlow Lite来实现图像分类。1. Azure自定义视觉服务
Azure自定义视觉服务简化了机器学习模型的创建和培训-无需具备Artificail Intelligence(AI)或机器学习(ML)的经验。使用Custom Vision服务的Web门户,我们可以执行以下操作而无需编写任何AI / ML代码:- 下载培训图片
- 在图像中标记标签/对象标签
- 重复(通过更多训练数据使模型变得更好)
- 就是这样-Custom Vision负责其余工作!
2. TensorFlow Lite
TensorFlow Lite是一个开放源代码的机器学习平台,使我们能够在物联网和移动设备中使用TensorFlow。TensorFlow Lite和TensorFlow可在GitHub上的开源上获得。使用Azure + Xamarin.Android实现图像分类
完整的示例图像分类应用程序可从GitHub上获得。1.模型训练
使用Custom Vision服务的Web门户,我们首先训练图像分类模型。1.在Custom Vision服务Web门户上,单击“ 新建项目”。2.在“ 创建新项目”窗口中,设置以下参数:- 名称: XamarinImageClassification
- 说明:识别图像中的对象
- 资源: [创建新资源]
- 项目类型:分类
- 分类类型:多标签(每个图像有多个标签)
- 域:常规(紧凑型)
- 出口能力:基本平台
3.在“ 创建新项目”窗口中,单击“ 创建项目”。4 .在XamarinImageClassification窗口中,单击“ 添加图像”。5.选择包含用于标识的对象的图像。6.在“ 图像上载”窗口中,添加标签注意:在此示例中,我们正在使用蘑菇图像。7.在“ 图像”窗口中上传点击上传注:守上传图片,直到你为每个标签至少5张图片8.在窗口右上角的XamarinImageClassification窗口中,单击“ 训练模型”按钮(齿轮的绿色图像)。9.在“ 选择训练类型”窗口中,选择“ 快速训练”。10.在“ 选择训练类型”窗口中,选择“ 训练”。2.从Azure自定义视觉服务中导出经过训练的模型
现在我们已经训练了模型,现在将其导出以在我们的移动应用程序中使用。这将使我们能够在没有Internet连接的情况下使用该模型,这将确保用户的最佳隐私,因为他的照片永远不会离开移动设备。要导出模型,请执行以下操作:1.在页面顶部的XamarinImageClassifcation窗口中,选择Performance选项卡2.在Performace选项卡上,单击Export按钮(向下箭头)3.在Choose your platform窗口中,选择TensorFlow4.在“ 选择平台”下拉列表中,选择TensorFlow Lite5.在“ 选择平台”窗口中,选择“ 下载”。3.将TensorFlow Lite导入我们的Xamarin.Android应用
1.在我们的Xamarin.Android项目中安装适当的NuGet软件包注意:此NuGet软件包是由Microsoft Xamarin团队创建的一个开源项目。它包含了C#绑定在原TensorFlow精简版库,它可以在我们的Xamarin.Android使用2应用程序。解压导出模型,我们从下载自定义视觉服务门户网站注: ZIP文件是labels.txt和model.tflite:- labels.txt包含准备在Custom Vision网站上进行培训期间创建的图像标签
- models.tflite是我们用于预测的机器学习模型。
3.在Visual Studio的Xamarin.Android项目中,右键单击Assets文件夹。4 .在弹出菜单中,选择“ 添加” →“ 现有项...”。5.在“ 添加现有项”菜单中,选择两个最近解压缩的文件:6.在Visual Studio中,在Xamarin.Android → Assets中,右键单击labels.txt。7.在弹出菜单中,选择Properties8.在Properties窗口中,选择Build Action → Android Asset9。在Visual Studio中,在Xamarin.Android → 资产,右键点击models.tflite10.在弹出的菜单中选择属性11.在属性窗口,选择生成操作 → Android的资产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
{
const int FloatSize = 4;
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);
var streamReader = new StreamReader(Application.Context.Assets.Open("labels.txt"));
var labels = streamReader.ReadToEnd().Split('\n').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToList();
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[]>();
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;
}
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;
}
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;
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。进一步研究的材料
检查下方的链接: