この記事は ハンズラボ Advent Calendar 2017 19日目の記事です。
@tuki0918です。
最近、趣味・お仕事で少しReact Nativeを触る機会があり、以前から気になっていたCore MLに手を出してみました。
最終的には自分で作成した学習モデルを使用して予測するようにしたかったのですが、変なところで5-6時間ハマってしまったため既存のモデルを動かすところまで対応としました。
React Nativeについては こちら
Core MLについては こちら
成果物について
分類対象の画像と分類結果を表示する簡単な画面を作成しました
ソースコードについては こちら に置いていますので、基本的に要点のみ記載していきます。
目次
- プロジェクトを作成する
- Native Moduleの準備する
- React NativeからNative Moduleにアクセスする
- CoreMLのサンプルのモデルを準備
- CoreMLの実装
- React NativeからCore MLを呼び出す
プロジェクトを作成する
今回のプロジェクトはXcodeを利用するため、下記コマンドを使用して進めています。
$ react-native init AwesomeProject
Native Moduleの準備する
公式にObjective-C と Swift のネイティブモジュールの作成方法が記載されています。
今回はCoreMLの実装が目的のため、PromisesとSwiftのネイティブモジュールの作成を参考に
プロジェクトのディレクトリ階層・ファイルが下記になるようにファイルを作成しました。
import Foundation
@objc(RNCoreML)
class RNCoreML: NSObject {
@objc(findEvents:findEventsWithResolver:rejecter:)
func findEvents(name: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
do {
resolve(name);
} catch {
reject(nil, nil, nil);
}
}
}
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(RNCoreML, NSObject)
RCT_EXTERN_METHOD(findEvents:(NSString *)name findEventsWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@end
#import <React/RCTBridgeModule.h>
最終的にはここから少し引数など変更しましたが、上記でもネイティブ側との動作確認はできると思います。
React NativeからNative Moduleにアクセスする
JS側からは呼び出したいファイルで下記のように記載することでNative Moduleを利用できました。
import { NativeModules } from 'react-native';
const RNCoreML = NativeModules.RNCoreML;
// promise なので async/awaitでもいいね
RNCoreML.findEvents('ABC').then(name => {
console.log(name); // ABC
});
CoreMLのサンプルのモデルを準備する
アップル公式のこちらのサイトより
GoogLeNet, Inception v3, VGG16などよく目にする学習モデルが用意されていますが
モバイル向けのMobileNetをダウンロードし、Xcodeプロジェクトに追加しました。
ハマったポイントとして、mlmodelプロジェクトに追加すると自動でモデルのクラスを作成してくれますが、
実際にSwiftから呼び出す場合はヘッダーファイルにimport文を書く必要がありました。
#import <React/RCTBridgeModule.h>
#import "MobileNet.h"
CoreMLの実装
基本的には他の方の実装を参考にしました。
しばらくの間、ちょこちょこ修正すると思うので興味のある方は下記コードを確認下さい。
筆者は Objective-C と Swift がほぼ解らないため、主に こちら の記事を参考にさせて頂きました
React NativeからCore MLを呼び出す
元々あるApp.jsを少し修正する形で修正しました。
stateのimageURLに分類したい画像を入力することで、最初に紹介した成果物のような見た目になり、Core ML上で予測した値が反映されます。
import React, { Component } from 'react';
import {
Image,
Platform,
StyleSheet,
Text,
View,
NativeModules
} from 'react-native';
const RNCoreML = NativeModules.RNCoreML;
export default class App extends Component<{}> {
state = {
imageURL: '分類したい画像のURL',
identifier: '-',
confidence: 0
};
componentDidMount() {
this.predict();
}
/**
* 画像の分類予測
*/
predict = () => {
const { imageURL } = this.state;
RNCoreML.predict(imageURL).then(data => {
this.setState({
identifier: data.identifier,
confidence: data.confidence
});
});
};
render() {
const { imageURL, identifier, confidence } = this.state;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Image style={{width: 150, height: 150}} source={{uri: imageURL}} />
<Text style={styles.instructions}>
identifier: {identifier}
</Text>
<Text style={styles.instructions}>
confidence: {confidence}
</Text>
</View>
);
}
}
... 略
最後に
最近はアウトプットしてなかったこともあり、なかなか書く内容が決まりませんでした。
Qiita自体も3年ぶりの投稿だったようです、2018年はアウトプットを少しずつ増やしていきたいですね。
今回のソースコードは こちら です。
※ カメラを活用したものや自分で作成した学習モデルで試せていないため、
しばらくの間は時間を見つけて内容を修正・機能を追加などするかもしれません。
ハンズラボ ハンズラボ Advent Calendar 2017 明日20日目は @kurapy-n です!よろしくお願いします。