Xamarin.iOS CoreML和Vision简介

写在前面:

在2017年的WWDC大会上,随着iOS 11的发布,随之而来的还有一系列新的特性和功能,同样也带来了独特的布局适配问题。在这次大会中,苹果推出了CoreML框架,能够将机器学习应用在移动端上,这等于在一些online的基础上提供了offline方式,可以说在实际的开发过程中,能在一些特定的业务需求上能提供极大的帮助。

什么是机器学习?

机器学习,也就是目前被大家经常提起的Machine Learning,也可以说是现在很火的一个技术,它也是人工智能最核心的内容。比如说横扫世界棋坛大名鼎鼎的阿尔法狗(AlphaGo),或者已经深入大家生活场景的图片识别、语言翻译、云歌曲推荐等等,这其实都是机器学习的具体实际应用的结果。

机器学习就是一种能让计算机不需要进行不断人工手动编程添加功能,而能自己学习的人工智能技术。它不是通过具体的编码算法,而是在大量的模型数据中找到一个合适的模式从而让计算机能够不断的发展和完善自身算法。

这个技术所要模拟的就是一个庞大而复杂的‘神经网络’,这个'神经网络'就需要大量的训练好的模型(model)来提供数据,使得这个'神经网络'能对各种输入(inputs)产生出一个对应的输出结果(outputs),并且还能通过不断的训练数据来提高自己的算法准确性。

这里的核心其实就是训练各种模型(model)来处理各种不同的情况和需求。比如说有了一个专门识别人脸的模型,给一个输入图片他就能把人脸位置输出出来等等等等,最后如果将无限多的训练好的模型都结合起来,那这个计算机可能就能像人一样应对各种情况还能不断地自我完善。下图是机器学习的一些应用场景:

CoreML是什么

Core ML根据官方文档里的这张图就可以看出,其实它的作用就是将一个训练好的ML模型,转换成我们的app工程可以直接使用的对象。利用该模型可以基于新的输入数据而进行预测,也就是利用了机器学习的结果。比如,如果一个模型在一个地区的历史房价数据上进行了训练,那么它就可能能够根据房子的卧室或客厅数量来预测房价。

Core ML 为设备性能进行了优化,从而减少了内存占用和功耗。严格在设备上运行能够确保用户数据的隐私,并且能保证你的应用在没有网络连接时也能够工作和响应。构建完成的Core ML又作为其他更高级框架的基础,比如支持用于图像分析的 Vision 框架,用于自然语言处理的 Foundation类,以及用于评估已经学习到的决策树的 GameplayKit。如下图:

  • vision:高性能的图像分析和图像识别。这部分应用于人脸追踪,人脸识别,文本识别,区域识别,二维码识别,物体追踪,图像识别等。
  • Nattural Language processing:自然语言处理。用于语言识别,分词,词性还原,词性判定等。
  • GamePlayKit:游戏制作,构建游戏。用于常见的游戏行为如随机数生成、人工智能、寻路、和代理行为。

Vision是什么

Vision是一个高性能的图片分析库,他能识别在图片和视频中的人脸、特征、场景分类等。你如果打开Vision的官方文档看,官方对他包含的所有类做了分类,比如有Face Detection and Recognition(人脸检测识别)、Machine Learning Image Analysis(机器学习图片分析)、Barcode Detection(条形码检测)、Text Detection(文本检测)等等。

大概可以这样去理解:Vision库里就已经自带了很多训练好的模型,这些模型是针对上面提到的人脸识别、条形码检测等等功能,如果你要实现的功能刚好是Vision库本身就能实现的,那么你直接使用Vision库自带的一些类和方法就行。

而当你要使用一个你在网上找的训练好的模型或者你自己训练好的模型的时候,才需要CoreML来将这个相当于‘第三方’模型转换成app认得的类,之后才能使用这个模型,同时也结合上面提到的Vision的Machine Learning Image Analysis(机器学习图片分析)分类下的类和方法来使用这个模型进行图形分析或者Vision其它的一些模型进行一系列分析操作。

CoreML Samples

下面给大家介绍官网给出的一个Mars Habitat Pricer sample,用以预测火星上的殖民地价值

1.给项目中添加model

将已经编译好的一个以.modelc为后缀的model添加到Resources项目文件夹中,然后设置这个文件夹下所有文件的build actionBundleResource

2.加载model

在我们使用model之前,我们需要使用MLModel.Create这个静态方法去加载model

var bundle = NSBundle.MainBundle;
var assetPath = bundle.GetUrlForResource("MarsHabitatPricer", "mlmodelc");
NSError mlErroe;
model = MLModel.Create(assetPath, out mlErroe);
3.设置参数

当我们开始使用这个模型之前,我们需要用Xcode打开我们的model,查看需要相应的inputs和outputs分别是什么,同时传入模型参数以及获取结果时都需要使用一个继承IMLFeatureProvider的容器类,这个类相当于一个字典,其中包含string的key,以及与之相对应的MLFeatureValues,每个feature value可以是string,number,array,data或者image buffer。

public class MarsHabitatPricerInput : NSObject, IMLFeatureProvider
{
    public double SolarPanels { get; set; }
    public double Greenhouses { get; set; }
    public double Size { get; set; }

    public NSSet<NSString> FeatureNames => new NSSet<NSString>(new NSString("solarPanels"), new NSString("greenhouses"), new NSString("size"));

    public MLFeatureValue GetFeatureValue(string featureName)
    {
        switch (featureName)
        {
            case "solarPanels":
                return MLFeatureValue.Create(SolarPanels);
            case "greenhouses":
                return MLFeatureValue.Create(Greenhouses);
            case "size":
                return MLFeatureValue.Create(Size);
            default:
                return MLFeatureValue.Create(0);
        }
    }
}

通过以上这种方式,我们的输入参数就可以被CoreML所识别,其中public NSSet<NSString> FeatureNames => new NSSet<NSString>(new NSString("solarPanels"), new NSString("greenhouses"), new NSString("size"));中的FeatureNames NSSet必须跟model所要求的输入保持相同。

4.使用model

使用model需要实例化我们自定义的继承了IMLFeatureProvider的容器类,将pickerview中三列的值传入MarsHabitatPricerInput,然后调用GetPrediction方法,然后通过调用GetFeatureValue方法,获取到相应的输出

void updatePredictedPrice()
{
    var pricerInput = new MarsHabitatPricerInput()
    {
        SolarPanels = datasource.GetValue(pickerView.SelectedRowInComponent(0), Feature.SolarPanels),
        Greenhouses = datasource.GetValue(pickerView.SelectedRowInComponent(1), Feature.Greenhouses),
        Size = datasource.GetValue(pickerView.SelectedRowInComponent(2), Feature.Size)
    };

    // Use the ML model
    NSError prErr;
    var outFeatures = model.GetPrediction(pricerInput, out prErr);
    var result = outFeatures.GetFeatureValue("price").DoubleValue;
    priceLabel.Text = "Predicted Price (millions) " + priceFormatter.StringFor(new NSNumber(result));
            
    Console.WriteLine(prErr == null ? $"result was {result}" : "Unexpected runtime error " + prErr.Description);
}

CoreML With Vision Framework Samples

CoreML也可以与Vision框架结合使用对图像进行操作,例如形状识别,人脸识别等其它操作。下面这个CoreML With Vision Samples中采用了CoreML和Vision 。该示例将Vision框架中的rectangles recognitionMNINSTClassifier.mlmodelc相结合,以识别照片中的手写数字。

1.创建一个Vision CoreML model

使用CoreML加载MNISTClassifier模型后,将其包装在一个VNCoreMLModel 模型中,使得该模型可用于图片处理。以下代码还创建了两个Vision请求:首先用于在图像中查找矩形,然后用CoreML模型处理矩形获取其中的数字:

// Load the ML model
var bundle = NSBundle.MainBundle;
var assetPath = bundle.GetUrlForResource("MNISTClassifier", "mlmodelc");
NSError mlErr, vnErr;
var mlModel = MLModel.Create(assetPath, out mlErr);
var model = VNCoreMLModel.FromMLModel(mlModel, out vnErr);

// Initialize
RectangleRequest = new VNDetectRectanglesRequest(HandleRectangles);
ClassificationRequest = new VNCoreMLRequest(model, HandleClassification);
2.开始Vision处理
// Run the rectangle detector, which upon completion runs the ML classifier.
var handler = new VNImageRequestHandler(ciImage, uiImage.Orientation.ToCGImagePropertyOrientation(), new VNImageOptions());
DispatchQueue.DefaultGlobalQueue.DispatchAsync(()=>{
        NSError error;
        handler.Perform(new VNRequest[] {RectangleRequest}, out error);
});
});

通过传入一个CIImage对象给Vision Framework,之后根据第一步创建的VNDetectRectanglesRequest请求,当矩形识别完毕后会执行相应的HandleRectangles回调函数。

3.处理Vision操作的结果

当开始执行HandleRectangles回调函数之后,裁剪图像以提取第一个矩形,将矩形图像转换为灰度,并将其传递给CoreML模型。

void HandleRectangles(VNRequest request, NSError error) {
var observations = request.GetResults<VNRectangleObservation>();
// ... omitted error handling ...
var detectedRectangle = observations[0]; // first rectangle
// ... omitted cropping and greyscale conversion ...
// Run the Core ML MNIST classifier -- results in handleClassification method
var handler = new VNImageRequestHandler(correctedImage, new VNImageOptions());
DispatchQueue.DefaultGlobalQueue.DispatchAsync(() => {
    handler.Perform(new VNRequest[] { ClassificationRequest }, out NSError err);
 });
}
4.使用CoreML

通过传入处理完成之后的CIImage对象给MNISTClassifier后,根据第一步创建的VNCoreMLRequest请求,当数字识别完毕后会执行相应的HandleClassification回调函数。

void HandleClassification(VNRequest request, NSError error){
var observations = request.GetResults<VNClassificationObservation>();
... omitted error handling ...
var best = observations[0]; // first/best classification result
// render in UI
DispatchQueue.MainQueue.DispatchAsync(()=>{
    ClassificationLabel.Text = $"Classification: {best.Identifier} Confidence: {best.Confidence * 100f:#.00}%";
});
}

传入的request参数中包含CoreML Request的详细信息,通过调用GetResults<VNClassificationObservation>()方法返回可能的结果结合。

写在最后:
到此在Xamarin.iOS中使用CoreML和Vision的案例介绍就完成了,之后也会给大家带来CoreML with Azure Custom Vision Service的介绍,包括使用工具转化第三方Model的介绍。可以看出对于集成CoreML来说,其实不是特别复杂,但是其中的算法可以说是非常高深的,我也会继续保持对CoreML的关注,分享更多的相关内容给大家。

到这里Xamarin.iOS CoreML和Vision的介绍就完成了,希望能对您有所帮助。


——End 有问题可以加我微信,大家一起讨论,加好友前请备注您的简称,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容