Ionic 4(PWA Toolkit) + Capacitorでカメラを動かして顔認識してみる

この記事はアドベントカレンダー2日目の記事です。
本記事では、Ionic4(PWA Toolkit)とCapacitorを使ってカメラ起動+顔認識をやろうと思います。

・[PWA Toolkit](https://ionicframework.com/pwa/toolkit)
Ionic4を使ってPWAを素早く組むためのもの。

・[Capactor](https://capacitor.ionicframework.com)
Cordovaの後継でJavaScriptとネイティブをブリッジするライブラリ。
※下のツイートの動画を読むとイメージ湧くとおもいます。
https://mobile.twitter.com/Ionicframework/status/1061990236631244800

今回、PWA ToolkitとCapacitorを使ってハイブリッドな顔認識アプリを作りたいと思います。

## プロジェクトを立ち上げる

PWA Toolkitでプロジェクトの生成は以下のコマンドを入力

```
$ npx create-stencil ionic-pwa
```

プロジェクト名が尋ねられますので適当な名前をつけましょう。
今回はプロジェクト名「capacitor-camera-facedetect」としました。

```
✔ Project name › capacitor-camera-facedetect

✔ All setup  in 22 ms

  Next steps:
   $ cd capacitor-camera-facedetect
   $ npm start

  Further reading:
   - https://beta.ionicframework.com
```

プロジェクトが生成されるので移動してnpm installしましょう。

```
$ cd capacitor-camera-facedetect
$ npm install
```

npm installが終わったら一旦プロジェクトを起動してみましょう。

```
$ npm run start
```

これで、Ionic4で作られたPWA対応のサイトが立ち上がります。

![Screen Shot 2018-11-29 at 22.34.47.png](https://qiita-image-store.s3.amazonaws.com/0/165335/7e65e641-400f-6fae-6f38-205d89ba8b0e.png)

Ionicを触ってる人からすると見慣れた青色ですね。
ちなみにこの時点でLighthouseのパフォーマンス100点がでる爆速サイトです。これについてはこちらの記事もどうぞ。
[Ionic4(stencil)で爆速でLighthouse100点のサイトを立ち上げる](https://qiita.com/xiaca/items/2a7d0a731ec6df6873b7) 


## Capacitorのインストール

次はCapacitorのCLIとcoreをインストールします。

```terminal
$ npm install --save @capacitor/core @capacitor/cli
```

インストールが終わったら次は、capacitorの初期設定です。

```terminal
$ npx cap init
```

途中、アプリ名とバンドルIDを求められるので入力します。

```terminal
? App name capacitor-facedetect
? App Package ID (in Java package format, no dashes) com.example.app
✔ Initializing Capacitor project in capacitor-camera-facedetect in 6.28ms


🎉   Your Capacitor project is ready to go!  🎉

Add platforms using "npx cap add":

  npx cap add android
  npx cap add ios
  npx cap add electron

Follow the Developer Workflow guide to get building:
https://capacitor.ionicframework.com/docs/basics/workflow
```

次に、各々のプラットフォームを追加しましょう。

```terminal
 $ npx cap add android
 $ npx cap add ios
 $ npx cap add electron
```

※iOS、Androidは前準備が必要になります。@rdlaboさんが書いたこちらの記事がより詳しいです。
[新しいHTML5 APPプラットフォーム「Capacitor」を試してみた](https://qiita.com/rdlabo/items/c76e0321096318489513)

プラットフォームの追加が終わったら、この時点でAndroid、iOS、Electron、Web全てにビルド可能なプロジェクトが出来上がります。

## カメラを動かす
次は、カメラを動かします。Capacitorの標準プラグインにバンドルされているので、src/components/app-home/app-home.tsxに以下のように変更すればOKです。

```diff
+ import { Component, Prop, State } from "@stencil/core";
+ import { Plugins, CameraResultType } from "@capacitor/core";

+ const { Camera } = Plugins;

@Component({
  tag: "app-home",
  styleUrl: "app-home.css"
})
export class AppHome {
+  @State() src: string = "";
+  @Prop({ connect: "ion-pwa-camera-modal" })
+  cameraModal: HTMLIonPwaCameraModalElement;

 
+  async takePicture() {
+    const image = await Camera.getPhoto({
+      quality: 90,
+      allowEditing: true,
+      resultType: CameraResultType.Uri
+    });
+    var imageUrl = image.webPath;
+    this.src = imageUrl;
+  }
 
   render() {
     return [
       <ion-header>
         <ion-toolbar color="primary">
           <ion-title>Home</ion-title>
         </ion-toolbar>
       </ion-header>,
 
       <ion-content padding>
-        <p>
-          Welcome to the PWA Toolkit. You can use this starter to build entire
-          apps with web components using Stencil and ionic/core! Check out the
-          README for everything that comes in this starter out of the box and
-          check out our docs on{" "}
-          <a href="https://stenciljs.com">stenciljs.com</a> to get started.
-        </p>
+        <img src={this.src} />
+        <ion-button onClick={() => this.takePicture()}>Camera</ion-button>
 
-        <ion-button href="/profile/ionic" expand="block">
-          Profile page
-        </ion-button>
       </ion-content>
     ];
   }
 }

```

次にWeb、ElectronのカメラのUI用に `@ionic/pwa-elements`をインストールします。

```terminal
$ npm install @ionic/pwa-elements
```

※このプラグイン、`@ionic/core`と依存関係でエラーがでやすいです。もしエラーがでたら、ちょっとpackage.json書き換えたやつを用意してるのでこれ使ってもらってもよいです。

```terminal
npm i https://github.com/scrpgil/ionic-pwa-elements.git#change-dependencies-build
```

最後に、`@ionic/pwa-elements`をインポートします。`src/global/app.ts`にimportの設定を追加します。これでコーディングは終わりで。

```diff
  import '@ionic/core';
+ import '@ionic/pwa-elements';
```

これで、カメラプラグインの設定は終わりです。プロジェクトを起動してカメラを起動させてみます。

```
$ npm run start
```

[デモサイト](https://capacitor-stencil-camera-test.netlify.com/)

![output.gif](https://qiita-image-store.s3.amazonaws.com/0/165335/e8ca0104-da68-c7ab-d682-2ccb437b7923.gif)


そして、Capacitorを使ってるメリットとしてこの時点でiOS、Android、Electronでも同様にカメラが動作します。
まずは、プロジェクトをビルドして、それぞれのプラットフォームにコピーします。

```
$ npm run build 
$ npx cap copy 
```

あとは、それぞれのIDEを操作すればおkです。

```
$ npx cap open ios
$ npx cap open android
$ cd electron/ && npm run electron:start
```

※electronはエラーがでます。詳しくは後述・・・

### Electronでエラーがでる問題
(2018/12/2時点)PWA Toolkit + Electronの組み合わせだとエラーがでます。この問題を解決するために `<base href="./">` にしたり、electronのバージョンをあげてみたりしましたがうまく動作させれませんでした(一様、`ion-router`を使わなければ回避可能)
おそらくPWA Toolkitじゃなくて@ionic/angularを使えばこの問題はでないでしょう。
GitHubに同件のissueが上がってるので興味ある方は是非。
[Multiple errors on capacitor electron app](https://github.com/ionic-team/capacitor/issues/888)


## 顔認識(おまけ)
せっかくなのでclmtrackrを使って顔認識してみました。
[デモ](https://capacitor-camera-facedetect.netlify.com/)
※PC推奨(Canvasのレスポンシブ対応さぼってるので...)
※顔認識の精度は撮影の状況、カメラの性能によって変わります。精度悪くてもCapacitor、Ionicのせいじゃないです。

試しに「フリー素材 写真 顔」で検索して出てきた女性の顔写真です。うまく認識できていますね。
![Screen Shot 2018-12-01 at 21.09.19.png](https://qiita-image-store.s3.amazonaws.com/0/165335/1a82cb4a-cb5c-4328-b25b-dcc983da238e.png)


## ソースコード
本記事のソースコードはGitHubにアップロードしてあります。
[GitHub](https://github.com/scrpgil/capacitor-camera-facedetect)
* ぜひともスターください

## まとめ
以上のように非常に簡単にハイブリッドなカメラアプリを立ち上げることができました。ここまでは完全に1ソースかつ、iOS、Androidは自動的にUIが変わります。
Capacitor使ってて嬉しかったのは
・インストールが早い。
・npx capコマンドで色々楽できる
・Webもカメラ用のUIが用意されてる
てところです。

あと今回、Capacitor触っていて「ひょっとしてあらゆるSPAのサイトは瞬間でアプリにできるんじゃね？」と思いました。今度、手元にあるサイトを色々アプリ化してみようと思います。
それでは。