专栏首页一棹烟波coreml之通过URL加载模型

coreml之通过URL加载模型

在xcode中使用mlmodel模型,之前说的最简单的方法是将模型拖进工程中即可,xcode会自动生成有关模型的前向预测接口,这种方式非常简单,但是更新模型就很不方便。

今天说下另外一种通过URL加载mlmodel的方式。具体可以查阅apple开发者官方文档 https://developer.apple.com/documentation/coreml/mlmodel:

流程如下:

1.提供mlmodel的文件所在路径model_path

NSString *model_path = "path_to/.mlmodel"

2.将NSSting类型转换为NSURL,并根据路径对模型进行编译(编译出的为.mlmodelc 文件, 这是一个临时文件,如果需要,可以将其保存到一个固定位置:https://developer.apple.com/documentation/coreml/core_ml_api/downloading_and_compiling_a_model_on_the_user_s_device)

NSURL *url = [NSURL fileURLWithPath:model_path isDirectory:FALSE];
NSURL *compile_url = [MLModel compileModelAtURL:url error:&error];

3.根据编译后模型所在路径,加载模型,类型为MLModel

MLModel *compiled_model = [MLModel modelWithContentsOfURL:compile_url configuration:model_config error:&error];

4.需要注意的是采用动态编译方式,coreml只是提供了一种代理方式MLFeatureProvider,类似于C++中的虚函数。因此需要自己重写模型输入和获取模型输出的类接口(该类继承自MLFeatureProvider)。如下自己封装的MLModelInput和MLModelOutput类。MLModelInput类可以根据模型的输入名称InputName,传递data给模型。而MLModelOutput可以根据不同的输出名称featureName获取预测结果。

这个是头文件:

#import <Foundation/Foundation.h>
#import <CoreML/CoreML.h>

NS_ASSUME_NONNULL_BEGIN

/// Model Prediction Input Type
API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0))
@interface MLModelInput : NSObject<MLFeatureProvider>

//the input name,default is image
@property (nonatomic, strong) NSString *inputName;

//data as color (kCVPixelFormatType_32BGRA) image buffer
@property (readwrite, nonatomic) CVPixelBufferRef data;

- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithData:(CVPixelBufferRef)data inputName:(NSString *)inputName;

@end


API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0))
@interface MLModelOutput : NSObject<MLFeatureProvider>

//the output name, defalut is feature
@property (nonatomic, strong) NSString *outputName;

// feature as multidimensional array of doubles
@property (readwrite, nonatomic) MLMultiArray *feature;

- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithFeature:(MLMultiArray *)feature;
@end

NS_ASSUME_NONNULL_END

这个是类方法实现的文件:

@implementation MLModelInput

- (instancetype)initWithData:(CVPixelBufferRef)data inputName:(nonnull NSString *)inputName {
    if (self) {
        _data = data;
        _inputName = inputName;
    }
    return self;
}

- (NSSet<NSString *> *)featureNames {
    return [NSSet setWithArray:@[self.inputName]];
}

- (nullable MLFeatureValue *)featureValueForName:(nonnull NSString *)featureName {
    if ([featureName isEqualToString:self.inputName]) {
        return [MLFeatureValue featureValueWithPixelBuffer:_data];
    }
    return nil;
}

@end


@implementation MLModelOutput

- (instancetype)initWithFeature:(MLMultiArray *)feature{
    if (self) {
        _feature = feature;
        _outputName = DefalutOutputValueName;
    }
    return self;
}

- (NSSet<NSString *> *)featureNames{
    return [NSSet setWithArray:@[self.outputName]];
}

- (nullable MLFeatureValue *)featureValueForName:(nonnull NSString *)featureName {
    if ([featureName isEqualToString:self.outputName]) {
        return [MLFeatureValue featureValueWithMultiArray:_feature];
    }
    return nil;
}

@end

5. 模型预测,获取预测结果。上面这两个类接口写完后,就可以整理输入数据为CvPixelBuffer,然后通过获取模型描述MLModelDescription得到输入名称,根据输入名称创建MLModelInput,预测,然后再根据MLModelOutput中的featureNames获取对应的预测输出数据,类型为MLMultiArray:

MLModelDescription *model_description = compiled_model.modelDescription;
NSDictionary *dict = model_description.inputDescriptionsByName;

NSArray<NSString *> *feature_names = [dict allKeys];
NSString *input_feature_name = feature_names[0];
NSError *error;
MLModelInput *model_input = [[MLModelInput alloc] initWithData:buffer inputName:input_feature_name];

id<MLFeatureProvider> model_output = [compiled_model predictionFromFeatures:model_input options:option error:&error];

6.读取MLMultiArray中的预测结果数据做后续处理..

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 光场相机重聚焦原理之——光场的参数化表征

    博主最近在搞光场相机方面的研究啦,好了废话不多说,开始!  1. 一些前言废话 首先,来一下光场的基本概念,来自百度百科。光场(light field):就是指...

    一棹烟波
  • libJPEG-turbo库使用示例代码

    libJPEG库是用于编码数据为JPEG格式或者解码JPEG格式图片的常用库,OpenCV读取图像底层实现就是利用libJPEG库,而libJPEG-turb...

    一棹烟波
  • 光场相机重聚焦之二——Lytro Illum记录光场

    上一节中大概讲述了光场相机和光场的参数化表示,这一节就说一下光场相机内部是如何记录光场以及实现重聚焦的。 博主用的是Lytro Illum,所以就以Illum为...

    一棹烟波
  • MSM8909的触摸屏驱动导致的熄屏后重新亮屏速度慢的原因!【转】

    转自:https://blog.csdn.net/kk20000/article/details/83041081

    用户3033338
  • SAP 云平台的一些有用链接 - 保证持续更新

    SAP Cloud Platform console client for the Neo environment enables development, d...

    Jerry Wang
  • ASP.NET MVC 4 RC的JS/CSS打包压缩功能

    打包(Bundling)及压缩(Minification)指的是将多个js文件或css文件打包成单一文件并压缩的做法,如此可减少浏览器需下载多个文件案才能完成网...

    张善友
  • 两个玻璃球 测试极限高度

    一道有趣的智力题目: 已知,玻璃球从某高楼落到地面会摔碎,楼的最大高度为100层,给你两个玻璃球,请你最快的测出,能使玻璃球摔碎的最低楼层... ? ...

    zhaoolee
  • iOS UITextField 使用与方法解读

    UITextField是IOS开发中用户交互中重要的一个控件,常被用来做账号密码框,输入信息框等。

    珲少
  • 决策树模型算法研究与案例分析

    用决策树对需要测试的实例进行分类:从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到其子结点;这时,每一个子结点对应着该特征的一个取值。如此递归...

    伏草惟存
  • Java调用Python爬虫

    用java调用python的爬虫程序,是一件很有意思的事情, 但解决方法大多不靠谱,作者花了两天的时间,动手实践,最终完全解决了问题 ? java-p...

    zhaoolee

扫码关注云+社区

领取腾讯云代金券