Now, AI is one of important technologies.
Almost all platforms have API sets of AI. Following list is technology names per platform.

  • Windows 10: Windows ML
  • Android: TensorFlow
  • iOS: CoreML

Xamarin can call native API sets using C#. It means you can implement AI feature on your app using Xamarin. This article will be introducing how to use AI APIs with Xamarin.Forms.

Create a project

Open Visual Studio 2017, then create a new project that is Mobile App (Xamarin.Form) of Cross-Platform category. And then select Blank, select Android, iOS, Windows(UWP) and .NET Standard.


Create a Xamarin.Forms project

Add base feature that exclude AI to here. I'll use a take photo feature in this app. So, add Xam.Plugin.Media NuGet package to all projects, then setup projects in accordance with the readme file shown. And then edit MainPage.xaml like below:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="AIApp.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:local="clr-namespace:AIApp"
Title="Safe Area"
ios:Page.UseSafeArea="True"> <StackLayout>
<Image
x:Name="picture"
Aspect="AspectFill"
VerticalOptions="FillAndExpand" />
<Label x:Name="output" HorizontalOptions="CenterAndExpand" />
<StackLayout Orientation="Horizontal">
<Button
Clicked="PickPhotoButton_Clicked"
HorizontalOptions="FillAndExpand"
Text="Pick a picture" />
<Button
Clicked="TakePhotoButton_Clicked"
HorizontalOptions="FillAndExpand"
Text="Take a picture" />
</StackLayout>
</StackLayout> </ContentPage>

At next, edit the code behind like below:

using Plugin.Media;
using Plugin.Media.Abstractions;
using System;
using System.Threading.Tasks;
using Xamarin.Forms; namespace AIApp
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
} private async void TakePhotoButton_Clicked(object sender, EventArgs e)
{
await ProcessPhotoAsync(true);
} private async void PickPhotoButton_Clicked(object sender, EventArgs e)
{
await ProcessPhotoAsync(false);
} private async Task ProcessPhotoAsync(bool useCamera)
{
await CrossMedia.Current.Initialize();
if (useCamera ? !CrossMedia.Current.IsTakePhotoSupported : !CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Info", "Your phone doesn't support photo feature.", "OK");
return;
} var photo = useCamera ?
await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions()) :
await CrossMedia.Current.PickPhotoAsync();
if (photo == null)
{
picture.Source = null;
return;
} picture.Source = ImageSource.FromFile(photo.Path); var service = DependencyService.Get<IPhotoDetector>();
if (service == null)
{
await DisplayAlert("Info", "Not implemented the feature on your device.", "OK");
return;
} using (var s = photo.GetStream())
{
var result = await service.DetectAsync(s);
output.Text = $"It looks like a {result}";
}
}
}
}

In this code, using IPhotoDetector interface to detect a photo. The interface is just a method that is DetectAsync.

using System.IO;
using System.Threading.Tasks; namespace AIApp
{
public interface IPhotoDetector
{
Task<FriesOrNotFriesTag> DetectAsync(Stream photo);
} public enum FriesOrNotFriesTag
{
None,
Fries,
NotFries,
}
}

Create ML models

I use Microsoft Cognitive Services Custom Vision(https://customvision.ai) to create ML models. Create Fries and NotFries tags on the project of Custom Vision.
Custom Vision service has a feature that generate CoreML, TensorFlow and ONNX files. Please read the following document to know more information.

Export your model for use with mobile devices | Microsoft Docs

The point is that select General (compact) of Domains category when creating project.


Create new project

After training the model, you can export the ML models from Export button at Performance tab.


Export models

Choose your platform

Add Windows 10 implementation

Windows 10 has Windows ML feature.

Windows Machine Learning | Microsoft Docs

Add the onnx file to Assets folder on the UWP project, then generated a C# file for use the onnx file.


Add an ONNX model

Add PhotoDetector.cs file to UWP project, and then edit the file like below:

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Storage;
using Xamarin.Forms; [assembly: Dependency(typeof(AIApp.UWP.PhotoDetector))]
namespace AIApp.UWP
{
public class PhotoDetector : IPhotoDetector
{
private FriesOrNotFriesModel _model;
public async Task DetectAsync(Stream photo)
{
await InitializeModelAsync();
var bitmapDecoder = await BitmapDecoder.CreateAsync(photo.AsRandomAccessStream());
var output = await _model.EvaluateAsync(new FriesOrNotFriesInput
{
data = ImageFeatureValue.CreateFromVideoFrame(VideoFrame.CreateWithSoftwareBitmap(await bitmapDecoder.GetSoftwareBitmapAsync())),
});
var label = output.classLabel.GetAsVectorView().FirstOrDefault();
return Enum.Parse(label);
} private async Task InitializeModelAsync()
{
if (_model != null)
{
return;
} var onnx = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FriesOrNotFries.onnx"));
_model = await FriesOrNotFriesModel.CreateFromStreamAsync(onnx);
}
}
}

Add Android implementation

On Android platform, TensorFlow is popular library. In Java or Kotlin, there is tensorflow-android library.

TensorFlow AAR For Android Inference Library and Java API | Maven Repository

On Xamarin, there is wrapper library.

Xam.Android.Tensorflow | NuGet

The library was introduced following article of Xamarin Blog.

Using TensorFlow and Azure to Add Image Classification to Your Android Apps | Xamarin Blog

Add a model file and label file to Android project.


Add TensorFlow model

At next, I add the library to Android project, then create PhotoDetector.cs file to the project. At next, edit the file like below:

using Android.Graphics;
using Org.Tensorflow.Contrib.Android;
using Plugin.CurrentActivity;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms; [assembly: Dependency(typeof(AIApp.Droid.PhotoDetector))]
namespace AIApp.Droid
{
public class PhotoDetector : IPhotoDetector
{
private static readonly string ModelFile = "model.pb";
private static readonly string LabelFile = "labels.txt";
private static readonly string InputName = "Placeholder";
private static readonly string OutputName = "loss";
private static readonly int InputSize = 227;
private readonly TensorFlowInferenceInterface _inferenceInterface;
private readonly string[] _labels; public PhotoDetector()
{
_inferenceInterface = new TensorFlowInferenceInterface(CrossCurrentActivity.Current.Activity.Assets, ModelFile);
using (var sr = new StreamReader(CrossCurrentActivity.Current.Activity.Assets.Open(LabelFile)))
{
_labels = sr.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x)).ToArray();
}
} public async Task DetectAsync(Stream photo)
{
var bitmap = await BitmapFactory.DecodeStreamAsync(photo);
var floatValues = GetBitmapPixels(bitmap);
var outputs = new float[_labels.Length];
_inferenceInterface.Feed(InputName, floatValues, 1, InputSize, InputSize, 3);
_inferenceInterface.Run(new[] { OutputName });
_inferenceInterface.Fetch(OutputName, outputs);
var index = Array.IndexOf(outputs, outputs.Max());
return (FriesOrNotFriesTag)Enum.Parse(typeof(FriesOrNotFriesTag), _labels[index]);
} private async Task LoadByteArrayFromAssetsAsync(string name)
{
using (var s = CrossCurrentActivity.Current.Activity.Assets.Open(name))
using (var ms = new MemoryStream())
{
await s.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
return ms.ToArray();
}
} private static float[] GetBitmapPixels(Bitmap bitmap)
{
var floatValues = new float[InputSize * InputSize * 3];
using (var scaledBitmap = Bitmap.CreateScaledBitmap(bitmap, InputSize, InputSize, false))
{
using (var resizedBitmap = scaledBitmap.Copy(Bitmap.Config.Argb8888, false))
{
var intValues = new int[InputSize * InputSize];
resizedBitmap.GetPixels(intValues, 0, resizedBitmap.Width, 0, 0, resizedBitmap.Width, resizedBitmap.Height);
for (int i = 0; i > 8) & 0xFF) - 117);
floatValues[i * 3 + 2] = (((val >> 16) & 0xFF) - 123);
}
resizedBitmap.Recycle();
}
scaledBitmap.Recycle();
} return floatValues;
}
}
}

Add iOS implementation

The last platform is iOS. iOS has CoreML feature.

Core ML | Apple Developer Documentation

In Xamarin platform, you can use CoreML APIs. The documentation is below:

Introduction to CoreML in Xamarin.iOS | Microsoft Docs

Add the CoreML file to Resources folder of iOS project, and set CoreMLModel to Build Action.


Add CoreML file

At next, add PhotoDetector.cs to iOS project, then edit the file like below:

using CoreFoundation;
using CoreImage;
using CoreML;
using Foundation;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Vision;
using Xamarin.Forms; [assembly: Dependency(typeof(AIApp.iOS.PhotoDetector))]
namespace AIApp.iOS
{
public class PhotoDetector : IPhotoDetector
{
private readonly MLModel _mlModel;
private readonly VNCoreMLModel _model; public PhotoDetector()
{
var assetPath = NSBundle.MainBundle.GetUrlForResource("FriesOrNotFries", "mlmodelc");
_mlModel = MLModel.Create(assetPath, out var _);
_model = VNCoreMLModel.FromMLModel(_mlModel, out var __);
} public Task DetectAsync(Stream photo)
{
var taskCompletionSource = new TaskCompletionSource();
void handleClassification(VNRequest request, NSError error)
{
var observations = request.GetResults();
if (observations == null)
{
taskCompletionSource.SetException(new Exception("Unexpected result type from VNCoreMLRequest"));
return;
} if (!observations.Any())
{
taskCompletionSource.SetResult(FriesOrNotFriesTag.None);
return;
} var best = observations.First();
taskCompletionSource.SetResult((FriesOrNotFriesTag)Enum.Parse(typeof(FriesOrNotFriesTag), best.Identifier));
} using (var data = NSData.FromStream(photo))
{
var ciImage = new CIImage(data);
var handler = new VNImageRequestHandler(ciImage, new VNImageOptions());
DispatchQueue.DefaultGlobalQueue.DispatchAsync(() =>
{
handler.Perform(new VNRequest[] { new VNCoreMLRequest(_model, handleClassification) }, out var _);
});
} return taskCompletionSource.Task;
}
}
}

How does it run?

This is results run on Windows 10.


Chirashi sushi is not fries, French fries is fries.

On Android:


French fries is fries, Fried egg is not fries.

On iOS:


French fries is fries, Soup is not fries.

Conclusion

AI is very important technology. You can use it your apps on all platforms.
If you created apps using Xamarin, then you could add the AI feature by steps of this article.

Have a good programing.

Add AI feature to Xamarin.Forms app的更多相关文章

  1. Xamarin.Forms App Settings

    配合James Montemagno的Component [Settings Plugin],实现Xamarin.Forms的设置. 更新系统配置且不需要进行重启app. 方式一xml Xamarin ...

  2. Xamarin.Forms 开发资源集合(复制)

    复制:https://www.cnblogs.com/mschen/p/10199997.html 收集整理了下 Xamarin.Forms 的学习参考资料,分享给大家,稍后会不断补充: UI样式 S ...

  3. Xamarin.Forms 开发资源集合

    收集整理了下 Xamarin.Forms 的学习参考资料,分享给大家,稍后会不断补充: UI样式 Snppts: Xamarin Forms UI Snippets. Prebuilt Templat ...

  4. 整理 Xamarin.Forms - Plugins

    Open Source Components for Xamarin Xamarin官方整理的一些开源组件,有需要可以先到这里找 GitHub: xamarin/XamarinComponents: ...

  5. Add Languages to Your Xamarin Apps with Multilingual App Toolkit

    With Xamarin, you can extend your cross-platform apps with support for native speakers, reaching mar ...

  6. 菜鸟的Xamarin.Forms前行之路——从新建项目到APP上架各种报错问题解决方法合集(不定时更新)

    出自:博客园-半路独行 原文地址:http://www.cnblogs.com/banluduxing/p/7425791.html 本文出自于http://www.cnblogs.com/banlu ...

  7. 【Xamarin.Forms 1】App的创建与运行

    引言 本篇文章将从介绍Xamarin.Forms创建开始. 开发环境 Visual Studio 2019 16.6.2 Xamarin.Forms 4.6.0.726 Android 5.0 (AP ...

  8. 【Xamarin.Forms 2】App基础知识与App启动

    系列目录 1.[Xamarin.Forms 1]App的创建与运行 引言 本篇文章将介绍Xamarin.Forms中 App 基础知识和 App的启动. 开发环境 Visual Studio 2019 ...

  9. Xamarin.Forms开发APP

    Xamarin.Forms+Prism(1)—— 开发准备 准备: 1.VS2017(推荐)或VS2015: 2.JDK 1.8以上: 3.Xamarin.Forms 最新版: 4.Prism 扩展, ...

随机推荐

  1. Jvm垃圾回收器(终结篇)

    知识回顾: 第一篇<Jvm垃圾回收器(基础篇)>主要讲述了判断对象的生死?两种基础判断对象生死的算法.引用计数法.可达性分析算法,方法区的回收.在第二篇<Jvm垃圾回收器(算法篇)& ...

  2. TensorFlow实现XOR

    TensorFlow基础 1.概念 TF使用图表示计算任务,图包括数据(Data).流(Flow).图(Graph) 图中节点称为op,一个op获得多个Tensor Tensor为张量,TF中用到的数 ...

  3. c#中如何使用到模糊查询

    c#中如何使用到模糊查询,先举个最简单实用的例子,可在vs控制台应用程序中输出: 定义实体类:  public class Student        {            public int ...

  4. 【问题】VS问题集合,不用也要收藏防止以后使用找不到

    在日常的使用或者工作当中我们的vs会时不时的给我一些小“惊喜”.让我们有时候无可奈何.这不今天我又遇到了所以我决定记录下这些,方便以后再次出现好解决. 无法启动iis express web 服务器 ...

  5. jenkins实现以gitlab为代码仓库的构建

    简介 前一篇随笔是安装jenkins的过程,比较简单,这一次说一下用jenkins配置以gitlab为代码管理仓库的maven项目的完整个构建过程,以及我碰到的一些问题.由于是maven项目,所以我们 ...

  6. Ext.isIterable

    Ext.isIterable用于判断传入的参数是否为可迭代的 在这4种情况下,函数返回true 1:数组2:函数参数arguments3:HTML collections : NodeList4:HT ...

  7. Sublime Text3介绍和插件安装——基于Python开发

    Subime编辑器是一款轻量级的代码编辑器,是收费的,但是可以无限期使用.官网下载地址:https://www.sublimetext.com. Sublime Text3支持语言开发种类多样,几乎可 ...

  8. 驰骋开源的asp.net工作流程引擎java工作流 2015 正文 驰骋工作流引擎ccflow6的功能列表

    关键词: 驰骋工作流引擎   ccflow的功能列表   工作流功能列表  表单引擎功能列表 我们工作流引擎ccflow6重构之后对功能做了一些调整,要想快速了解ccbpm的功能,可以以下面列表为准 ...

  9. 如何将Eclipse的javaWeb项目改为IDEA的maven项目

    1.首先去IDEA开发工具创建一个maven项目,把该项目改为Web项目, a.在pom.xml中,添加packaging标签,值为war b.右键File,选中project structure, ...

  10. 简单的纯js三级联动

    参考这个  日尼禾尔  二级联动 写了三级联动 <!DOCTYPE html> <html> <head> <meta charset="UTF-8 ...