Safie APIとTensorflowjs で物体検出モックアップを作った話

**@kenmaro**です。
普段は主に**秘密計算、準同型暗号などの記事について投稿しています**。
秘密計算に関連するまとめの記事に関しては以下をご覧ください。

> - [秘密計算エンジニアを始めて２年半が経った。](https://qiita.com/kenmaro/items/48059dd60f79e80f5ef8)
> - [秘密計算エンジニアを始めて3年が経った。](https://qiita.com/kenmaro/items/a1d90a074d552b7bf886)


## 概要

Safie 株式会社さんが提供される、Safie API　

https://developers.safie.link/

を触る機会があり、どのようなAPIがあるのかを調べたり、簡単な物体検出のできるWebアプリを作ってみました。
また、どういう流れで使用開始できるのかなども備忘録としてまとめようかと思います。


## 成果物
![Screen Shot 2022-03-29 at 21.47.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/a7cd8318-1ba0-f179-9eac-5141818e18f3.png)

このようなウェブアプリを作りました。
フロントから数秒おきに画像APIを呼び、
クライアントサイドでTensorflowjsの物体検出モデルを用いて物体検出を行うアプリケーションです。
スクリーンショット上では、机の上のハサミを認識しています✂️

## API利用申請の流れ

まず、SafieAPIの利用申請を行う必要があります。
申請フォームをみると、会社等の情報を入力する必要があり、基本的に個人的にAPIを利用申請することはできないように一見見えますが、
実際はAPI利用規約にもある通り、個人でも利用の申請が行えるみたいです。

申請が行われると、数日後くらいにAPIの

- Client ID
- Client Secret

がメールで送られてきます。それらを使って、OAuth2.0によるトークンの取得をAPIを用いて行います。

トークンが取得できると、そのトークンを使って他のAPIを呼ぶことができるようになります。

この辺りは、公式のAPIドキュメントに従うことになります。

私がドキュメントを眺めた感想ですが、APIを活用して簡単なアプリなどを作る際、

- HLSプロトコルに従って動画をストリーミングする　LiveAPI
- 位置情報を取得する　位置情報取得API
- デバイスから画像をその都度取得する　画像取得API
- 動画内に写っている人の数を返す　AI People Count　API

あたりを使って開発することになるのかなあと思いました。
詳しくは下の公式のAPIドキュメントを一読してみるとどのようなものが使えそうか確認することができます。

https://openapi.safie.link/redoc?_gl=1*1w8ow84*_gcl_aw*R0NMLjE2NDQ0NzI2NjMuQ2p3S0NBaUE2WTJRQmhBdEVpd0FHSHliUFlWS1N4VmdnRm9JbUsySk5ydGM0elRYQ0hqNWZIRnRXbnlDOE1Xak9zWTB4ZzJtY0NMMVF4b0NkMjBRQXZEX0J3RQ..*_ga*MTIyMzYwMTE2MC4xNjQzMTY1MDQ2*_ga_77TLT5XJ71*MTY0ODUzNDgzNS4xMy4xLjE2NDg1MzUzNzcuMA..&_ga=2.163282808.597125155.1648534836-1223601160.1643165046#tag/auth


## デバイスのレンタル

私はSafieのカメラを持っていなかったため、試しにレンタルをして開発してみることにしました。

https://safie.link/plan/

ここに料金プランなどが載っていますが、買うかどうか決めていない場合は、まずはレンタルすることができます。

私は今回は、一番コンパクトに使えそうな

![Screen Shot 2022-03-29 at 15.41.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/50ca9d55-e4cc-385b-66e3-726acf77f6f3.png)

このSafie Pocket２　をレンタルしてみることにしました。

レンタルを申し込んでから１週間ほどでレンタル機が届きました。
また、レンタル機と共に、クラウド上で撮影している動画を見ることのできるプラットフォームへのログイン情報なども届きました。


## 簡単に触ってみた初感

まず、このSafie Packet2ですが、非常にいいなと思った点がいくつかあります。

- コンパクトで持ち運びやすいこと
- カメラのカバーを開けると、撮影が自動で始まること
- 使用開始からなにもセットアップせずに、クラウド連携ができること

などです。

#### コンパクトで持ち運びやすいこと
についてですが、このカメラをつかうシーンとして書いてある通り、
現場で作業員が胸やヘルメットにこのカメラを装着するなど簡単にできるくらい軽く小さいため、持ち運びやすかったです。

#### カメラのカバーを開けると、撮影が自動で始まること
青色のカバーを開けると、録画ボタンなどを押さずとも録画が始まるため、簡単に録画が開始できるところがいいと思いました。
閉めると自動で録画がストップするため、録画の開始と停止が非常に直感的に操作できていいなと思いました。

#### 使用開始からなにもセットアップせずに、クラウド連携ができること
クラウド上に動画が常にアップロードされ、動画を確認したり保存したりできるSafieクラウド

https://safie.link/app/devices/camera

へのアクセスと、カメラとの連携ですが、
なにかセットアップが必要なのかと思っていましたが、クラウド上で動画をみるときに、
レンタル機を使い始めるとすでにクラウドとの連携が完了していたため、セットアップは不要で非常に簡単だなと思いました。
この辺りのDXはすごく使いやすいなと思いました。

## 私が今回作ってみた構成
今回は、時間的制約などもあったため、かなり雑に簡単なウェブアプリを作ってみようと思い立ち、このような構成にしました。

![Screen Shot 2022-03-29 at 16.10.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/5b3a8255-de6c-d95a-7dd9-00f0c7e78433.png)

かなり一般的な構成だと思いますが、tensorflowjs を用いることで、物体検出モデルの実行をブラウザ上で行うような構成にしています。
こうすることで、ブラウザ上で環境が完結しているため、クラウド型のサービスを展開するSafieの設計と相性がいい気がしました。
また、ブラウザベースなのでアクセスする端末を選ばないところがいいところかなと思います。

最初はモバイルアプリにするつもりでしたが、時間的制約のため今回はウェブアプリの形にしました。
モバイルアプリにも近いうちチャレンジしようと思います。

ウェブ上で画像（動画）をみながら、AIを用いて解析をかけるというシステムは非常に汎用的であるため、
ここにシナリオを付けることでいろいろなアプリケーションが作れるなあと思いました。



## 開発した流れ

ここでは、少しだけ開発の詳細と、実施した際にかかった時間を書いていきたいと思います。

### デバイスのセットアップ（１時間）
Safieのカメラを用いて、トークンの発行を行い、APIにリクエストを実際に送れるか検証しました。

比較的スムーズに行っていたのですが、デバイスIDをどこから取得するか、というところ（セーフィクラウド上でデバイスのストリーミングを見るときの、URIから取得できます）
を勘違いしてしまい、そこでIDが間違っていると知らずに、APIの投げ方が悪いと思ったため時間を費やしました。
サポートの方に聞いて初めて気づいたのですが、よくある間違いらしいので気をつけるべきだと思います。

### フロントエンドにビデオを入れる工程（3時間）
フロントエンドはもともとNextjsについては使ったことがあったため、そこまで問題なく開発できました。
実際の開発では、Safieカメラを常に手元においてはいなかったため、とりあえずPCのインカメの映像をウェブに投影してモックアップを作ることにしました。
このような経験はなかったため、普通に時間がかかりました。
フロントエンドを自分の知らない技術スタックでやるとすると、この倍くらいはかかったのではないかと思います。


### Tensorflowjsの理解とモデル実装（2時間）
Tensorflowjsを使い、ブラウザ上でモデルの実行を行いたいと考え、
Tensorflowjsは初めて使ったため、ライブラリの理解に少し時間を要しました。
モデルのロード、推論の仕方、推論結果のパースなど、一通り実装するのは少し手間がかかりました。
また、推論結果のボックスをCanvasに書いて、それを元の画像に載せたのですが、Canvasの操作などもあまりやったことがなかったため、そこそこ時間がかかりました。

### SafieAPI との繋ぎ込み（3時間）
インカメを使ってリアルタイムで推論することはできるようになり、
ここから実際にSafieAPIから取得した画像に対して同じことをやる流れで進めました。
ここでいくつか知識不足もありハマりポイントがあり、結構時間がかかりました。

例えば、

- フロントからAPIを呼ぶとCOR問題があり、バックエンド(Nextjsの/apiから）から呼ぶ必要があること
- axiosを用いて画像データのレスポンスを取得する際にハマった（後述の神記事を見つけれなければたぶんずっとはまっていた）
- 取得した画像をフックを使ってimgに挿入するところがよくわからなかった（これも結局スタックオーバーフローがなければ確実にはまっていた）


などでした。
これらを解決して、ようやくやりたかったところまで実装を終えることができました。



## まとめ

今回は、SafieAPIを使ってなにかできないかと思い、かなり汎用的なユースケースである、
画像を取得してから独自のAIモデルを使用する、という実装をやってみました。

書いたコードは後ほどgithubに上げようと思います。
モデルをいろいろ工夫してシナリオをつければ、ハッカソンなどでも活用できそうですし、
普通にいろいろ問題を解決できそうなので、結構面白いなと思いました。

次はモバイルネイティブな実装もやってみたいなと思いました。



今回はこの辺で。

@kenmaro




## 助けられたリンク(備忘録的抜粋）

https://qiita.com/ksh-fthr/items/ba7c80252edad0e7c66c

https://stackoverflow.com/questions/66182345/converting-axios-returned-image-into-something-vue-can-display-in-img