Junpei Qawasaki

博報堂アイ・スタジオという会社でテクノロジーをベースに新規事業とかインタラクティブなものとかを色々とやっております

UnityのToonShader(UTS2)を30分で理解しながらお試しする。

ちょっと直近でVTuberぽいのをやる事があって、unityのToonShaderを触ってました。
使ったのは「UnityChanToonShader ver2(以降UTS2)」で、ドキュメントもサンプルも充実してて大変ありがたいんですが、概要を把握するまでゼロからだとちょっと時間かかるんですね。なので例によって「とりあえず感覚的に知りたい」って人向けにざっくりお試しの手順を書き残していきます。

そもそもToonShaderとは

いわゆる「アニメぽい」表現をする為のUIシェーダー。同じモデルでこんな変化が出せます。
f:id:jkawasaki:20190617135653p:plain

3Dモデルでも見た目を良い感じにする事が出来るだけでなく、自己発光とか光や影の表現も色々出来るので汎用性です。(適用したら見た目が変わるって訳ではなく、好みの表現にするにはパラメーター調整が必要)今回触った結果は、こちら。アニメとかCG表現詳しくないのである程度ですが。

f:id:jkawasaki:20190617155927p:plain
仕上がり例(所要時間1hくらい)
UTS2のDLはUnity-Chanのサイトか、Githubのどちらかから持ってきてくださいませ。
日本語のreadmeはこちら

さっそく、使ってみましょう

1. ShaderOnlyパッケージをダウンロード

今回は最短ルートを行くので、余計なものが入っていないシェーダーだけのパッケージを入れます。
前述したUTS2全体だと色んなものが入っているので、個人のプロジェクトに抜き出すのは結構大変です。シェーダーだけの.packageも落とせるので、それを使います。以下のリンクからダウンロードして適用したいプロジェクトに適宜インポートしましょう。
ここでは空のプロジェクトにユニティちゃんのモデルだけ入れたものを使っていきます。

UnityChanToonShaderVer2_Project/UTS2_ShaderOnly_v2.0.7_Release.unitypackage at master · unity3d-jp/UnityChanToonShaderVer2_Project · GitHub

2 とりあえずマテリアルに全アタッチ

シェーダーは適用したいマテリアルにアタッチして使います。
UTS2はアタッチしただけで劇的に変わるものじゃないのですが、まずはアタッチしましょう。
unity-chanの場合は「body, eye,hair, skin, face」あたりです。Projectフォルダで検索して右クリックして場所を探ればたどり着けるので、全部選択状態にして一括で「UnityChan ToonShader/Toon_DoubleShadeWithFeather」を適用します。
f:id:jkawasaki:20190617130710p:plain

適用するとこんな感じにめちゃくちゃになるけど、それでok。次の手順へ。
f:id:jkawasaki:20190617141330p:plain

3 間違えてるパラメーターを直す

3-1. ”BasicColorStep”を0に
まず白く出てる影を消します「body, face, skin, hair」のマテリアルを選んでBasic LookDevsの”BasicColorStep”を0にします
f:id:jkawasaki:20190617141230g:plain

3-2. 「Body」と「Hair」のCullingModeを”Culling Off”にします

3-3. 「mat_cheek」のシェーダーをUnityChanToonShader/NoOutline/ToonColor_DoubleShadeWithFeather_Transparentに変更して、"Use baseMap α as Clipping Mask”をONにします(透過の云々で必要なので)
ONするとチークが消えますが、”ClippingLevel"を動かすと浮き出てきます。これと”Tranaparency Level”でチークを良い感じに設定します

f:id:jkawasaki:20190617141838g:plain

3-4. 「eye」のマテリアルにUnityChanToonShader/NoOutline/ToonColor_DoubleShadeWithFeather_TransClippingに変更して、"Use baseMap α as Clipping Mask”をONにします。cheekと微妙に違うのでご注意を。これで黒目と白目がちゃんと分かれます。

f:id:jkawasaki:20190617145346g:plain

ここまでで大まかな設定は完了

ToonらしいUIを調整していく

以下の3点をいじると良い感じになります。

①影の当たり具合(body,hair,skin,face)
Basic Liikdevs:Shading Step and Feather SettingsのBasicColor Stepで影の当たり具合を調整。ShadeFeatherで影をなじませる
f:id:jkawasaki:20190617164902g:plain
ほんとはMesh分割してそれぞれにマテリアルつけて調整する方が良くなるぽいですが、今回は割愛。

②RimLight(body,hair)
RimLightSettingのColorでオーラ色を調整。Powerのスライダでオーラの出具合を調整


③アウトライン(body,hair,skin,face)
OutlineSettingのWidthとColorで調整
f:id:jkawasaki:20190617170444g:plain

もっと細かいことを知りたい、という方はこちらのチュートリアル動画が良いです。
字幕も入ってて細かく解説されてるのですが初見だとちょいちょい止めながらセッティングしなきゃなので、時間はかかります。

出来上がり

で、上記の調整をコツコツと仕上げたらこんな感じになります。
f:id:jkawasaki:20190617161120g:plain


UTS2はInspectorでいじりながらリアルタイムに調整出来るのが良さなので、カメラを回すスクリプトが入ってると背面も確認しながらやれるので便利です。逆に背面確認しないと影とかが思った感じにならない場合が多いので。

そんなこんなで汎用的にするために自己発光のプロトタイプも書ければと思ったけど、思いの外長くなってしまったのでまた次回に。


では。

IntelRealSence(D435i/T265)をunityで動かす。

コンピュータビジョン(CV)てご存知でしょうか。
すごい簡単に言うと「機械が見る現実世界」みたいなものです。昨今の自動運転やディープラーニングなどの画像解析が分かりやすいんですが、それ以外にも様々なセンサ類も含めて機械が現実世界で起きてる事を認識して、その情報をトリガーにインタラクションを起こすみたいな用途で使われます。

今回はそんなCVの分野で使うデバイス「RealSence」について。
CV関連はopenCVを自前でカスタマイズしてどんな環境からも呼べるようにするのが一番汎用性高いし、パフォーマンス出やすいっていう理論は分かりつつもゼロから自前CV作るのは大変なのでワタシは機材に頼ります。

これまでCV系センサの代表だったのが「KINECT」で、モーションキャプチャーとかデプス(深度)を使った制作をする事も多かったんですが、2017年にKINECTも生産終了しており、ハードが進化してるのにずっとKINECT使い続けるのも如何なものかと思ってIntelのRealSenceを本腰入れて使おうと思い始めました。RealSence自体は結構昔からあって使った事もあるんですけどね。公式のunityのpackageも出てきたので汎用性高そうと思って。

f:id:jkawasaki:20190421114915j:plain
RealSence(左:D435i 右:T265)

で、両方購入しました。
今ならswitch scienceで在庫もあるですよ。
KINECTより全然小さいし、電源も謎のアダプタ使わなくて良いので使いやすい。

D435iは深度計測が可能なステレオビジョンの深度カメラで、深度センサ×2、RGBセンサ、IR投射器を搭載しつつ、USB給電で動作(KINECTは別途電源が必要だった)するデバイス。T265は深度は搭載されておらず、トラッキングに特化したデバイスでハード側でV-SLAMアルゴリズムを直接実行する事でレイテンシ 6 ms未満を実現するものになってます。

「で、結局何に使うの?」って声が回りから出て来そうなんですが、イベントとかインスタレーションを作るときのinputはコレか画像検出のどちらかで今後は制作して行こうかなと思ってる次第ですよ。


ただし、

unityで使うにはSDKコンパイルしてビルドしてDLL作ってとかの事前準備がいくつかあります。
これについてのWebの情報が少なかったり(または古かったり)win環境に慣れてない人への「優しい情報」がなくて数日、沼にハマったのでこのエントリではその辺りを書き残しておこうと思った次第です。
Windowsや既にRealSenceの開発に慣れてる人にとってはあんまり為にならないので、そういう人はスルーしてください)


1. Macで動かそうと思ってる貴方へ。


僕も普段のunity開発はMacメインでやってるのでMacで動かそうかなと思ったのですが、色んな情報見るとRealSenceのMac SDKは非公式で、結論から言うとハードの全機能も使えないし、cmakeの時点で結構エラー吐くので早々にWindowsに切り替えました。
最近だとHoudiniとかもそうだしグラボだけじゃなくてセンサ系も含めてMacだけで開発やっていくのは難しい時代。



2. Windows環境準備


■RealSence SDKをインストールする
とりあえずはSDKをインストールしましょう。
SDKにはReakSenceViewerも含まれていて、これを使えば別に自分で開発しないでもRealSenceの基本機能を見る事が出来ます。
SDKの.exeはGitHubにあるので、適宜ダウンロード&インストールしてください。この記事を書いてる時(2019年4月21日)の最新はSDK 2.0。
f:id:jkawasaki:20190421154010g:plain
T265 Viewerサンプル。ステレオ魚眼とカメラトラッキング


で、こちらがD435iのデプスサンプル2つ。

f:id:jkawasaki:20190421134450g:plain
2D

f:id:jkawasaki:20190421134530g:plain
3Dもいける


ちなみにD435iはWindows10じゃないとデバイス認識してくれませんでした。
T265はWin8.1でも動くのですが、Dも動かしたい人は先にアップデートした方が良きです


■unityとVisualStudioをインストールする
最終的にこの2つが無いとどうにもならないので、インストールしましょう。
このエントリを書いてる段階では以下のバージョンを使ってます。

unity …2018.3.12f1
visual Studio …2017(2019でも問題ないです、たぶん)
Windows10


■Gitをインストールする
Gitの最新版をインストールします。
これが無いとこの後のcmakeする時にエラーが出ます。


■Cmakeをインストールする
Macではふつーに使えるcmakeですが、Windowsでは以下のツールが必要です。特にカスタム設定の必要は無いので、手順に従ってインストールして下さい。
cmake.org

ちなみにmacでcmakeだけやってdllだけ移せば良くない?って思うかもしれないですがコンパイル時に環境判定が入るのでエラーになるだけです。


3. librealsenseのダウンロード


セッティングで重要なのが「librealsence」です。
以下、GitHubからダウンロードして任意の場所に解凍(配置)します。面倒だったら"ダウンロード"配下でも問題ないです。
※注
GitHubでデフォルト表示されるリポジトリは最新版のMasterになってます。
最新は安定版とは違う(Pre-release)ので、何が起こるか分からないので避けた方が懸命です。このエントリでは安定版(Latest-Release)のbuild 2.19.0を使ってます。
f:id:jkawasaki:20190420232512p:plain


4. librealsenseのコンパイル


ここまでの手順は詰まる所はなくて、ここからが本題です。
unitypackageが配布されてるとはいえ、そのままインポートしてSceneを実行してもエラーを吐きます。
unityで動かすには自PCの環境で以下2つのdllを作成してAssets/Pluginsの配下に配置する必要があります。

==
Intel.Realsence.dll
・realsence2.dll
==

librealsenseのビルド方法は以下に記載、と言う記事が多いのですが、肝心のページが英語なのでなかなか分かり難いので要点だけ説明します。
github.com


■buildフォルダの作成
ダウンロード・解凍したlibrealsenseは「librealsense 2.19.0」というフォルダになります。で、このrootで以下のコマンドを実行せよ、と説明には書いてあるのですが、実際の解凍フォルダはlibrealsense 2.19.0/librealsense 2.19.0 というディレクトリになっていて、下層の「librealsense 2.19.0」がrootになるので、このフォルダまでコマンドプロンプトで移動します。
移動したら以下のコマンドをコマンドプロンプトから実行します。

mkdir build
cd build
まぁ単純に librealsense 2.19.0/librealsense 2.19.0/build というフォルダを作っただけです。
で、その上でbuild配下で以下のコマンドを打ちます。
cmake .. -DBUILD_CSHARP_BINDINGS=ON -DBUILD_UNITY_BINDINGS=ON -DBUILD_SHARED_LIBS=ON -DDOTNET_VERSION_LIBRARY=3.5 -DCMAKE_GENERATOR_PLATFORM=x64

Gitさえ入ってれば2-3分で問題なくコンパイルが終了します。
記事によってはCMakeのGUIで実行すべき、みたいなのもあって諸々試して見ましたが、別にCMake GUIを使う必要はなさそうです。


4. VisualStudioでビルド


上記コンパイルが完了すると色々なファイルがbuild配下に出来上がります。
realsence2.slnをビルドという情報をたまに見ますが違うのでご注意を。
正確には
librealsense 2.19.0/librealsense 2.19.0/build/wappers/csharp/Intel.RealSence/配下のIntel.RealSence.slnファイルを右クリック「プログラムから開く」→「Visual Studio 2017」で開きます。
f:id:jkawasaki:20190421013212p:plain

開いたら特に設定は変えず[ビルド]→[ソリューションのビルド]でビルドを実行します。
ビルドが完了するとlibrealsense 2.19.0/librealsense 2.19.0/build/Debug配下にIntel.Realsence.dllとrealsence2.dllが出来上がってるはずです(ファイルのタイムスタンプから判断すると分かりやすい)

※エラーについて※
「realsense.libを開くことが出来ません」とか「ソースファイルを開けません "atlstr.h"」みたいなエラーが出る時はそもそもビルドしてるslnが違う可能性があります。binの中にlibとかヘッダーを探しに行くと迷いの森に入ることになります


5. unityのセッティング


セッティングっていうほどでは無いんですが、上記ビルドを完了したら、librealsense 2.19.0/librealsense 2.19.0/build/wappers/unity/Assets/RealSenceSDK2.0/Sceneの下の「StartHere」というunity sceneファイルをダブルクリックしてunityを起動します。

起動してもdllを配置してないとエラーが出るので、Assets直下に「Plugins」という名前のフォルダを新規作成して前行程で作成したIntel.Realsence.dllとrealsence2.dllをドラッグ&ドロップでコピーします。


6. Sceneの実行


お手持ちのIntel RealSence(D435iまたはT265)を接続した上でunityのSceneを実行します。場合によっては以下のように「デバイスが接続されてないエラー」が出るみたいですが、その場合は再起動しつつ、RealSenceViewerで表示されてるかを確認してください。


いざsceneを実行。

f:id:jkawasaki:20190421111224g:plain
unityで動いた。

この画像だけじゃ意味わかんないかもですが、T265の位置をunity側でリアルタイムにトラッキング出来てます。
ちょうどNintendo switchVRが出たので、それと合わせてなんかやろうかな。
ちなみにSDKのunity.packageにはdepthのサンプル6つとSLAMサンプルが1つ入ってます。

今回は動かすところまでが主題なので、ここまで。
サンプル動かしただけじゃないって話ですが、unity側で色々とやっていくのは次回以降に粛々と書きたいと思います。

ではー。

【IoT】LTE-M Buttonを触って概念を理解する (SMS/メール送信・Slack投稿・unity連携など)

f:id:jkawasaki:20181103113800j:plain
発表されてから予約日に即予約したSORACOMの「LTE-M Button」が届きました。

LTE-MもButtonも「よく分からんが、なんとなく理解したい」という人も一定層いるかなと思うので、基本的な所と触った所感を書いていきます。なるべく簡単に書くので概念で覚えて頂いてチャレンジャーが増えると嬉しいなと。

LTE-Mについて

まず、AmazonDashButtonとなにが違うの?って話ですが、概念で覚えるならばもうDashボタンのイメージでok。ボタン押したらAWSのLamdba※ってサービス上でプログラムが動きます。プログラムはカスタム出来るので好きに作る感じで、Dashはここのプログラムに欲しい製品を購入すると言う処理が書いてあって、Amazonでのお買い物が出来るって訳です。

大きく違うのは「回線」。
従来のDashボタンはWiFiのセッティングが必要で、つまりWiFi範囲外に出たら使えない。SORACOM LTE-M Buttonの大きな新規性はKDDILTE-M回線を使う所にあって気持ちとしては携帯と同じ気持ちで使えます。
LTE-M」はいわゆるLTE回線の「空いてる帯域」をやりくりして、上り/下りとも最大1Mbpsくらい(携帯の100分の1くらい)の通信が可能な通信キャリアならではのLPWAというもの。LPWAって言うとLoRaWANとかSigfoxとかが有名なところで、弊社でやってるというかメインのお仕事である「TREK TRACK」でもLoRa変調の仕組みを採用しております。
trektrack.jp

f:id:jkawasaki:20181104233730j:plain

Lambda … AWSAmazon)が提供するサーバーレスで処理が実行出来るサービス。Node.js (JavaScript)、PythonJava (Java 8 互換)、C# 、および Go で記述されたコードがサポートされてて何かと便利らしいけど、わたくし、あんま知らないです

■既存LPWAと比較したメリット・デメリット(個人的な所感)

メリットとしてはキャリアの回線を使うので携帯に近いイメージで使えます。とはいえ、厳密に同じではないらしいのでその辺りはKDDIさんのページをみて頂ければと。今の所、自分の生活圏で使う分には問題なさげです。
反面、デメリットとなるのはキャリア回線に依存するので圏外の場所で使おうとしてもどうにもならない所です。920MHz帯のLoRaたちはアンテナを自営する事で山の中とか電波の無い所でも使うことはできます。ただ、このアンテナ自営はコストと労力がかかる上に、通信を行うアンテナ(ゲートウェイ)は何かしらの回線に繋がってないといけないので一長一短ですね。
ゲートウェイは安いものでも1台100,000円近くしてしまうのと、工事したり電気通信事業の届出が必要だったりとかするので個人のモノづくりに向いていないのが現状で、920MHz帯はハード(電子工作)の知識が必要だったり、通信データ量がそもそも数byteでセンサー向けだったりと参入ハードルがあるのでまず触るのにもLTE-M良いし将来性もあると思います。

LTE-M Buttonで何が出来るのか

Buttonは1回押し、ダブルクリック、長押しの3つのアクションが使えます。それぞれの押し方をされたら何をするかはそのさきのプログラム次第。 ボタン(デバイス)単位でID管理されるので、どのボタンが押されたか、というのもLambda側で判定出来ます。

Training① 押したらSMS / メール送信をやってみる

今なら3980円というお手頃価格で手に入るボタン、とりあえず触ってみるというレベルであればプログラム書かないでも実行することが出来ます。まずは一番簡単なSMS送信orメール送信のやり方。

[前提]
SORACOMアカウントが必要です(LTE-M Button購入の時点で必要ですが)
AWSのアカウントが必要です

LTE-M Buttonの梱包を開けるとおもむろにデバイスと電池が入ってるだけで特に使い方は書いてないのですが、SORACOMのサイトに行くと丁寧に書いてあるのでいくつかWebで検索すればすぐに解決します。簡単に言うと4ステップ。

f:id:jkawasaki:20181104183325p:plain
①「AWS IoT 1 click」アプリを入手してデバイス登録
②SORACOM UserコンソールでLTE-M Buttonのデバイス登録をします。
③WSコンソールに「AWS IoT1-Click」からデバイスを登録
④Lambdaで新規関数を作成。
※SMSとメール送信はプログラム書かずに出来ます

■実行結果

ボタンを押して実行するとこのようにメールやSMSが飛んできます。今回は "たすけてボタン" と言う前提でたくさんの"たすけて"が送られてきます。

f:id:jkawasaki:20181103220811j:plain
実行結果

詳細はSORACOMさんの公式に書いてあるので、気になる方はぜひ。
サクッとやれます。
blog.soracom.jp


Training② Button押したらSlackにpost

次はSlack。これも情報としては既にWebに出ているので概要だけ。簡単に言うと3ステップ。

① Slack Webhook URLを発行する(所要時間3分)
まずは投稿したいSlackのワークスペースから「Webhook URL」を発行しましょう
② 次に処理を行うLambda関数を作ります(所要時間7分)
③ で、実行すればSlackに飛んできます(所要時間1分)

f:id:jkawasaki:20181104195617p:plainf:id:jkawasaki:20181104195532p:plain
関数作成

f:id:jkawasaki:20181104195524p:plain
Button押してSlackにpostされるの図

こちらも詳しいやり方は以下に載ってます。
SORACOM LTE-M Button powered by AWS をクリックしてSlackに通知する | Getting Started with SORACOM LTE-M Button | SORACOM Developers

LTE-Mボタンの企画アイデアを考える上で気にすべき事

用途が大変広そうなLTE-M Button、個人的にもまだアイデア出てきてないんですが触ってみてたら以下3点は気にしないといけないなと思いました。ここまで読んで「よく分からん」という方も以下3点は知っておいてください。

気にすべき① :押してから処理の実行まではラグがある
これ、省電力を実現する為にも必須らしいのですがButtonは押されてからセッション準備→投げるという動作をするので、そもそもLambdaの関数が実行されるまで10数秒のインターバルがあります。なので、どんなに電波が良くとも処理が軽くとも「押した瞬間何かが起きる」みたいな事にはならず、インタラクティブなものに使う場合、体験の設計が必要です。下のようにしばらく点滅して緑になったら処理完了という感じです。

youtu.be


気にすべき②:電波と実行回数上限
これは上でも触れたんですが、そもそも電波が無い所だと使えないのでご注意を。

気にすべき③:Lambda関数を挟むという事
Lambdaを挟む事で可能性は無限なのだけど、クライアント→サーバじゃなくてある意味、サーバ→クライアントになるです。なので例えばクライアント側に処理を投げたい時はそこの別スキルが必要になります。
と、いう事でunityと連携しようとしたら面倒だったというのを最後に記しておきます。

Training③ UnityとLambdaでなんかやる

今後、色々使っていきたいと考えるとまずは自分で扱いやすい環境での動作みたいなーと思っており、unityでどうにかならんかな、と思って試行錯誤してまずはunity→Lambdaに繋ぐところを作ってみた。
一応、AWSからSDKが出ているのだけどRoleを生成したりなんだりと前手順が複雑で結構な時間がかかった。。しかもunity だと悪名高いWWWの変更のタイミングをSDKがまたいでいてエラーの切り分けが大変。結果として繋ぐ事は出来たのだけど、ButtonClick→Lambda側で処理結果をUnity側で定期的に見るみたいな事をしないといけなくて、そこまでやっても何が出来る訳でも無いので今日はここまで。

f:id:jkawasaki:20181104204510p:plain
AWS SDKからLambda関数リスト表示したとこで中断。

Lambda連携はこちらの記事を参考にさせていただきました。
blog.be-style.jpn.com



■最後に

もっと先になると思われてたLTE-Mがすぐに触れる環境が整備されて大変ありがたいですね。プラットフォームが整備されるほどその技術の進化は早いんじゃないかなと思います。とはいえ、スマホLTE)を日常で使うのが当たり前の世の中で、LPWAならではの体験っていうものを直感的に伝えるにはどうすれば良いかは日常的に探さないといかんな、と思った次第です。


では。

【Python×Unity】パーソナルウェザーステーション「netatmo」からAPI経由でデータを取得する

f:id:jkawasaki:20181007110055j:plain
屋外&屋内の気象観測が出来る「netatmo」というセンサーを入手しまして。
写真左から屋内モジュール、屋外モジュール、風速計、雨量計です。数万円で精密な環境センサが手に入る時代。
とはいえ、製品自体は数年前に発売されたものなのだけど、農業とかアウトドア関連のものだと使い勝手良いと思っていて。
例えば「幕張メッセの今の二酸化炭素量」とか「港区のビル屋上の風速」みたいなのって、フツーはピンポイントで分からないのだけど、コレ置くだけで把握出来ます。なので、任意の地点の雨量を計測して、雨量が一定量超えたらXXする、みたいな事も出来るし、高機密性の家とかだと二酸化炭素濃度が上がりやすかったりとかするので、一定のCO2濃度超えたら換気するみたいなスマートホーム的な物にも使えそう。

パーソナルウェザーステーションといえど、精度は高いので台風とかそういう時にもピンポイント雨量がわかるだけでも中々便利でありまして、日本の各自治体で1台ずつ導入して頂いてなんか作らせてほしい。

それはさておき、コレをとりあえず触って行きます。「こんな段取りでセンサーの特徴理解していくよ」って話なので、馴染みが無い人にはくそつまらない記事だと思います。のでご了承くださいませ。

○netatmoについて

屋内センサ(親)はWiFiクラウドに繋がってて気温、湿度、騒音、二酸化炭素量なんかが収集されます。
別売りの屋外・風速・雨量モジュール(子)は電池駆動。屋内と無線で繋がってて風速とか雨量とか気圧とか取れます。
風速や雨量のデータを集めたい場合、通常だと専用のモジュールとシールド買ってArduinoやラズパイと繋げるという以下みたいな選択になりますが↓↓
ウェザーメーター(風向・風速・雨量) - Weather Meters/SEN-08942 - ネット販売
ざっくり考えても以下3点の理由で効率悪い。

・個々のモジュール制作にコストがかかる
・収集されるデータが生データなので成型するのが大変
・苦労して完成したとして、果たしてそのデータにどれだけ信頼おけるのか

風速についても超音波モジュールの組み合わせで安価出来る、みたいな記事もあるのだけど、実務で使うには信頼性が怪しい。
そんな訳で、辿り着いたのがnetatmoです。公式のアプリもあってちょっと設定するだけで以下のような管理画面でグラフ見れる、すごい。
f:id:jkawasaki:20181008180645p:plain

で、肝心のデータの正確さはどうなんだって話なんですが、家の外に置いてたらちょうど良く台風来まして。そのデータがこちら。
f:id:jkawasaki:20181008181023p:plain
大型台風で道路の木とか倒れてしまう時で相当な風速だったのだけど、壊れることもなく取得に成功。気圧も良い感じのカーブを描いてた。
ただ、風速がkm表記なんすよね。日本の場合はm/s表記がスタンダードなので、変換をかませないといけなくて、変換してみるとこの値が正しいのかどうなのかはまだちょっと微妙。

とはいえ、センサーとしての信頼度は高く使い勝手が良いのは分かったのでAPIから色々取得出来るようになりましょう。と。

○netatmo APIをターミナルから触ってみる


※基本的な部分は以下記事を参考にしてもらう前提で割愛※
NetatmoウェザーステーションAPIをさくっと呼び出す

netatmoの管理画面でアプリ登録をするとIDとsecret keyとか発行されるので、それを使います。
疎通確認するくらいなら以下のコマンドを打てばok。

curl -X POST https://api.netatmo.com/oauth2/token -d "grant_type=password&client_id=[自分のID]&client_secret=[自分のシークレットキー]&username=[メアド]&password=[パスワード]"

f:id:jkawasaki:20181008213934p:plain
こんな感じのaccess_tokenが返ってくるので、それが返って来るなら、少なくとも使える状態にはあるはず。
とはいえ、これでは何もデータが見れないので、まずはAPIから各種データを取得したい。
が、ちょっとSDKは個人的に好きな言語のが無かったのです。なのでまずはPythonで取得する事から始める。

Pythonでデータを取得する


今回はlnetatmoというライブラリを拝借。
github.comどうでもいいけどサムネの画像の主張がすごい。
2日くらい色んな手法を探したのですが、Netatmoを掘り下げて行くとネットの海を2周遊くらいして、最終的にこいつに行き着きます。一応、他にも2つくらいはやり方あります。

ex.py

#!/usr/bin/python3
# encoding=utf-8
import lnetatmo
#tokenを取得
authorization = lnetatmo.ClientAuth(
                clientId = "自分のID",
                clientSecret = "自分のシークレットキー",
                username = "メアド",
                password = "パスワード",
                scope = "read_station"
)
#天気情報の取得
weather_station = lnetatmo.WeatherStationData(authorization)
#天気情報の表示
print(weather_station.lastData())

で、こいつを実行すると、こうです。
f:id:jkawasaki:20181008183026p:plain

無事に各種、センサー値が返って来ました。
さて、これで色々出来るようになったのだけど、今回の目的としてはUnityでこのデータを触りたいという思いがあるので、UnityからPython経由で取得する方法を探ります(2018.10.8現在未完成)

○Unityでデータを取得する


今回参考にさせて頂いたのは以下のブログです。
【Unity】「IronPython」で Python から Unity API を呼び出す方法 - コガネブログ
Unity上でPythonを使う①【アセット組み込み編】 - kitao's blog
Unity上でPythonを使う②【外部ファイル読み込み編】 - kitao's blog

Python連携するにはIronPythonが良いらしいのだけど、ライブラリ自体が汎用的で複雑なので調べ方を間違えると把握するのむずい。
やりたかったのは後者のブログの内容なのだけど、これの通りだと残念ながら動作しなかったです。
前者の方がコードもシンプルだったので割と楽に動いた。
■exsample.cs

using IronPython.Hosting;
using UnityEngine;

public class Example : MonoBehaviour
{
    public TextAsset m_textAsset;

    private void Awake()
    {
        var text = m_textAsset.text;
        var engine = Python.CreateEngine();
        engine.Runtime.LoadAssembly(typeof(GameObject).Assembly);
        var scope = engine.CreateScope();
        var source = engine.CreateScriptSourceFromString(text);
        source.Execute(scope);
    }
}

で、Assetsの下に配置したPythonのコード(.txt)側でログ出力をしてるのだけど上記csコードが動かしてくれます。
f:id:jkawasaki:20181008183957p:plain

こんな感じに。
Pythonの中に書いたDebug.Logが出力されただけ。
て、よく考えたらこれ「UnityでPythonコード実行」じゃなくて「PythonでUnityのAPIが叩ける」なので、そもそも違う。

netatmoデータ持ってくるにはlnetatmoのライブラリを経由する必要があるので、このままでは叩けない。
そんで、ここまで来て一旦時間切れということもあるので本調査は終了。

本当は、UnityからnodeとPythonを自由に使えるようになったら色んなこういうAPI解放してる外部製品を触り放題だから、そういう所を目指してるのですが、まだいくつか触っていかないと見えんすね。

では。

GoPro HERO7 BlackのLiveStreamingを試す

GoPro HERO7 Blackを買いました。
f:id:jkawasaki:20180930184707j:plain

特にカメラ好きな訳でも無く、これまでGoPro自体はそこまで触ってなかったのだけど、HERO7で追加された機能は開発で応用したり企画でも使えるなーと思っての導入。新機能の中で琴線に触れた2点が「HyperSmooth」と「LiveStreaming」。で、今回はLiveStreamingを試してみたという話。

大前提としてGoProは購入してもマニュアルついてる訳では無くて、接続とかはアプリに従ってれば良い感じに出来るという思想です。とはいえ、個人的にもストリーミングの設定でハマったので、上手くいかない場合はこちらにあるマニュアルを見ると色々書いてあるので、ハマった人はぜひ。

さて、お仕事で使う前提で考えてるので、まずはGoProの映像がどうやってネットワークに出て行くかを知らないといけません。
結論から言うとスマホのAppで連携して外部に出ていきます。
接続を進めて行くと分かるんですが、BluetoothWiFiの共有で上手い感じにネットに出ていきます。Facebookの連携もスマホからやります。
ざっくり言うと以下のような感じですね。

f:id:jkawasaki:20180930180844p:plain

ここでポイントなのが

スマホ側から接続したいAPを指定出来る
・パーソナルホットスポットスマホの回線を使う事も可能

と、言う事です。
前者は高速なWiFiがある環境の時には使えるけど、GoProでLive配信したい時って屋外の環境が多いと思うので、その場合は後者を使う感じになります。
ちなみに、最初やろうとした時は何回やっても「カメラとの接続が切れました」って出て上手くいかずカメラの初期化&アプリ再設定したら治りました。おそらくなんだけど最初にBluetooth接続→WiFi接続をやるときにカメラの名前があったりとか、GoProアカウントとFacebookアカウントの連携が上手く言ってなかったので、同様の状況な人はやり直すとすんなり行くかと思います。

f:id:jkawasaki:20180930181709p:plainf:id:jkawasaki:20180930181706p:plainf:id:jkawasaki:20180930181722p:plainf:id:jkawasaki:20180930181717p:plainf:id:jkawasaki:20180930181714p:plain

だいたいこんな感じで、スマホの回線を使ってる場合はテザリングみたいな表示になります。この辺りのWiFiでカメラと接続、回線はキャリア回線を使うってシーンが例えばSONYのCameraRemoteAPIだと手動でIP指定したりとか、既存のWiFiが使えないとかの制約があるのに対してGoProはその辺りストレスなく使えるのでホスピタリティが高いなぁと思った次第です。

ちなみにFBアカウントは同じスマホ内に入れたFBアプリのアカウントに紐付くので、専用の配信アカウントとかでやりたい場合はFB側で入り直して連携すればそれに紐づきます。ライブストリーミングの設定自体が上手くいかん、と言う方は詳細な設定方法のURLが製品マニュアルに載ってるのですが、そこから直リンク叩くと404になったので、一応、こちらからライブストリーミングの設定方法に飛べます。ただ、英語しかないのと、あんまり詳しいことは書いてないです。

さて、Live配信の方ですが、HERO7自体がストリーミング出来ると言うのがウリで贅沢はいえないのですがクオリティは720p(または480p)になります。そしてネットワーク環境によるけど、ラグはそこそこあるので「超高解像度でリアルタイム配信」とか言ってしまうとそれは嘘になるのでご注意を。超クオリティのLive配信をしたい場合にはGoProじゃなくて、既存の高解像度配信の仕組みを使うのが良いです。

とはいえ、良いのがこのLive配信でも「Hyper Smooth」は生きるところ。ジンバルとか用意しなくともブレの無い画像でストリーミング配信が出来ます。逆に言うと定点カメラだとそんなに意味ないって感じすね。HERO7では夜景でのラプス撮影とかの機能も追加されてますが、それはストーミングでは使えません。あくまで目に見えてるのと同じような風景になる感じです。また配信範囲の設定はストリーミング前の設定画面で出来ますが、最初は「自分のみ」にしておいて配信が出来てからFacebook側で公開範囲を変えるのが良いかなと思います。でも事前に告知したい時とかは「公開」でやっておいて一時停止にするのが良いのかも。

撮影した画像とか、ハード仕様の詳細なんかは以下、「強火で進め」さんがまとめられておりますので割愛。
d.hatena.ne.jp
d.hatena.ne.jp

そんなこんなでスマホとGoProがあれば細々とした作り込みが不要で、手ブレ少ないLiveStreamが出来ると言うのは強力だと思っていて、今後、色々と活用が広がる気がしてます。
ただ、個人的には企画で使う際に「現場での設定のめんどさ」みたいなのは加味した方が良いかなと思いました。手放しで誰でも出来るものでは無いので、初期設定はしておいて、あとは使う度「こう使ってね」と言うマニュアルを簡単に作ればイベントなどでの実運用にも耐えれるな、と。あと、気になるバッテリーは配信せずに1時間くらいいじってたらバッテリー半分くらいまで減ったのと、自動で配信が切れる時間が15分だか30分だかであるので「配信前まで充電」して「15分配信したらバッテリー交換」みたいな使い方をある程度決めれば良いかなと思いました。長尺で回しっぱなし配信したい、みたいな時は有線で繋ぎながらで出来るけど、スマホ側かGoPro側がスリープに入ると切れるので、その辺りはそういう使い方したい場合に検証した方が良いかなと思いました。

今回はLiveStreamをするまでの流れの把握と、その実態を知るのがメインだったのでこの辺で。
次はGoPro APIを叩いてみるみたいなことをやってみたいなと思います。

【機械学習&IoT】星空と記念撮影する自動撮影ブースを作りました

f:id:jkawasaki:20180727115801j:plain

2018年3月のSXSWにも出展した自動撮影ソリューション『capture』をバージョンアップ。
captureは元々、特定物体検出のライブラリ「YOLO」をiPhone上で動かして、条件がそろったら自動撮影してくれるアプリで、ニセコでスキーの自動撮影を実験的にやってました。それについては以下のリリースをご覧くださいませ。

www.i-studio.co.jp

今回は"特別な瞬間を自動で撮影"というコンセプトはそのままに、アウトドア環境で星空と一緒に撮影出来るカメラを作るという企画で、撮影のためのグランピングブースから制作し、ブース内のLED照明とセンサと高感度カメラ(SONY α7)を同時制御してます。

f:id:jkawasaki:20180727115617p:plain

captureはいわゆるiOSアプリなので、星空を撮影するにはいくつかハードルがあります。ノイズ、シャッタースピードISO感度、絞りなど。※ちなみにカメラには詳しくないです

まず最初はiOS側でAV Foundationで設定をいじってどこまで撮影出来るか確認。→ノイズ多い。
確かに星は映るけど、ノイズ多すぎて駄目。

根本の原因であるノイズなのでハード的な限界はある為、考えたのがSONY CameraRemote API
簡単に言うとSONYのカメラ製品をプログラムから制御出来るヤツ。最終的にブースではiPhoneとカメラを設置にしなきゃなので大きさを考慮して"QX100"と言うものを中古で購入して試してみたところ、ノイズは大幅に低減。

f:id:jkawasaki:20180727121044p:plain

しかしながらこのQX100はやりたいことに大して大きな問題ありまして、リファレンス上は"Shutter Speed"と"ISO SpeedRate"のAPIでSet出来ると書いてあるけど実際にはエラーが返るという。

Camera RemoteのらSDK自体はもうあまり更新されてないのだけど、機体のファームウェアバージョンとかSDK最新じゃないと不具合起きるとのことで403 ForbiddenのままでQXは役割を終えました。

画質の最大化やバッテリー容量の観点からQXだと心許ないので、「α7」に変更

レンズはSEL28F20はフルサイズの28mm(カメラ詳しくないのであんまり分からない)。
カメラ決まったのでこれをiPhoneと一緒に設置出来るための筐体を制作。コストと運用しやすさを加味してシンプル&化粧板設計。
f:id:jkawasaki:20180727111711p:plain
f:id:jkawasaki:20180727111722p:plain

そして星が映っても人の顔がちゃんと映らないと意味が無く、大自然の中にカメラだけ置いてもそれが良い写真になるかは体験者に依存してしまうので、グランピングブースを制作して、LED照明をカメラと連動させる事に。
最終的なブース全体像と、スマホカメラとの差分はこんな感じです。
f:id:jkawasaki:20180727121744j:plain

LEDは撮影前、撮影中、待機中で、それぞれ個別に光量が変化。照明制御はRaspberryPiとiPhoneをBLE連携、LEDはI2C制御基盤を4枚。iPhone側と信号をラリーする形で自動撮影を進めております。

そんな感じで多分、星空と記念撮影に特化したブースは他であんまり無い物になったかと思います。
このブースは「ほしのしずくスタジオ」と言う名前で2018年7月28日より岩手県の雫石プリンスホテルに常設されますので、ぜひ!

★ Staff List
Art Director: Yosuke Sasagaki
iOS Engineer: Yuta Hirakawa, Takafumi Oyama
Device Engineer: Yasuyuki Ogino
3D WebViewer: Hiroshi Koi
Front and Backend Engineer: Kota Toda
Technical Director(Web):Yoshimasa Yokoyama
Product Design:Takumi Maezawa , Yosuke Sasagaki
Designer: Yosuke Sasagaki
PR : Miki Senoo , Takafumi Kato
Producer and Technical Director : Junpei Qawasaki

■ニュース記事は以下です
news.ibc.co.jp
news.biglobe.ne.jp