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. Python:游戏:贪吃蛇原理及代码实现

    一.游戏介绍 贪吃蛇是个非常简单的游戏,适合练手.先来看一下我的游戏截图: 玩法介绍:回车键:开始游戏空格键:暂停 / 继续↑↓←→方向键 或 WSAD 键:控制移动方向. 食物分红.绿.蓝三种,分别 ...

  2. .NET移动开发,关于发布IOS的方法(本人亲身经历折腾很久终于成功)

    前情提要:这位.NET程序员兄弟使用Smobiler开发了一个APP,尽管Smobiler云平台已经最大限度的简化了iOS应用的打包操作,但仍绕不开苹果公司强制要求的p12文件,p12文件需要开发者自 ...

  3. C#实现注册表 LocalMachine 目录下CURD工具类

    [1]注册表是什么?         百度百科 https://baike.baidu.com/item/%E6%B3%A8%E5%86%8C%E8%A1%A8/101856?fr=aladdin [ ...

  4. 你必须知道的.net读书笔记之第二回深入浅出关键字---对抽象编程:接口和抽象类

    请记住,面向对象思想的一个最重要的原则就是:面向接口编程. 借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程. 抽象类应主要用于关系密切的对象,而接口 ...

  5. Hibernate框架_搭建第一个Hibernate框架

    一.eclipse搭建 A.创建动态web项目 New-->Dynamic web project(web project) B.导入jar包 1.数据库驱动包 2.hibernate开发必须j ...

  6. Vue 无限滚动加载指令

    也不存在什么加载咯, 就是一个判断滚动条是否到达浏览器底部了. 如果到了就触发事件,米到就不处理. 计算公式提简单的   底部等于(0) =  滚动条高度 - 滚动条顶部距离 - 可视高度.  反正结 ...

  7. WebGL或OpenGL关于模型视图投影变换的设置技巧

    目录 1. 具体实例 2. 解决方案 1) Cube.html 2) Cube.js 3) 运行结果 3. 详细讲解 1) 模型变换 2) 视图变换 3) 投影变换 4) 模型视图投影矩阵 4. 存在 ...

  8. 小米平板6.0以上系统如何不用Root激活Xposed框架的步骤

    在异常多公司的引流,或业务操作中,大多数需要使用安卓的神一般的Xposed框架,几天前我们公司买来了一批新的小米平板6.0以上系统,大多数都是基于7.0以上版本,大多数不能够获取Root超级权限,虽然 ...

  9. linux 大冒险

    本来想搞一个nas系统,结果上来linux的贼船. 本来是看上了deepin深度linux,结果看到排名第一的manjaro 就忍不住手.通过hyper-v虚拟机安装,发现这个所谓的第一不知道第一在哪 ...

  10. 【工作分解法】IT人,你的工作“轻松”么?

    一.前言 假如读者是一个老板,下面有两位员工,工作难度一样,完成量一样,人品和责任心也一样.一位每天加班加点,废寝忘食的工作:而另外一位每天在座位上喝着咖啡,非常的轻松自如的工作.您会更器重哪一位? ...