Edited at

React NativeからCore MLを使用して画像分類するまで

More than 1 year has passed since last update.

この記事は ハンズラボ Advent Calendar 2017 19日目の記事です。

@tuki0918です。

最近、趣味・お仕事で少しReact Nativeを触る機会があり、以前から気になっていたCore MLに手を出してみました。

最終的には自分で作成した学習モデルを使用して予測するようにしたかったのですが、変なところで5-6時間ハマってしまったため既存のモデルを動かすところまで対応としました。

React Nativeについては こちら

Core MLについては こちら


成果物について

分類対象の画像と分類結果を表示する簡単な画面を作成しました

ソースコードについては こちら に置いていますので、基本的に要点のみ記載していきます。

iPhone_8_Plus_-_11_2.png


目次


  • プロジェクトを作成する

  • 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のネイティブモジュールの作成を参考に

プロジェクトのディレクトリ階層・ファイルが下記になるようにファイルを作成しました。

RNCoreML_swift_と_MobileNet.png


RNCoreML.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);
}
}

}



RNCoreMLBridge.m

#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



AwesomeProject-Bridging-Header.h

#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プロジェクトに追加しました。

RNCoreML_swift_と_MobileNet2.png

ハマったポイントとして、mlmodelプロジェクトに追加すると自動でモデルのクラスを作成してくれますが、

実際にSwiftから呼び出す場合はヘッダーファイルにimport文を書く必要がありました。


AwesomeProject-Bridging-Header.h

#import <React/RCTBridgeModule.h>

#import "MobileNet.h"


CoreMLの実装

基本的には他の方の実装を参考にしました。

しばらくの間、ちょこちょこ修正すると思うので興味のある方は下記コードを確認下さい。

https://github.com/tuki0918/react-native-coreml/blob/master/AwesomeProject/ios/RNCoreML.swift

筆者は Objective-C と Swift がほぼ解らないため、主に こちら の記事を参考にさせて頂きました


React NativeからCore MLを呼び出す

元々あるApp.jsを少し修正する形で修正しました。

stateのimageURLに分類したい画像を入力することで、最初に紹介した成果物のような見た目になり、Core ML上で予測した値が反映されます。


App.js

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 です!よろしくお願いします。