RGBカメラ画像処理による関節角度推定
大学の画像処理の実習で、実験の課題が出されました。
実験の内容としては、「今まで学習したことを使って、実験する価値のある画像処理プログラムを作成する」ことです。「実験する価値がある」というのは、すでに実現できるとわかっているものではなく、実験してみないとわからないものということでした。
そこで私はRGBカメラによる人間の関節角度推定システムを作ることにしました。
普段、開発をしていてRGBカメラしかない状況で、「深度センサーを組み込んだRGB-Dカメラのような距離情報を取得できるカメラがあれば…」ということが多々あります。例えば、iPhoneアプリ開発で、iPhoneのカメラを使ってセンシングする場合など.....
Kinectのような深度センサーが組み込まれたRGB-Dカメラなら関節推定はできる(と思う)のですが、RGBカメラでは普通にはできません。
システム構成
今回は腕の関節角度推定をしました。
肌色領域抽出とテンプレートマッチングがベースのシステムになっています。
簡単な流れとしては、
1. 上腕と前腕部分をテンプレート画像として抽出
2. 腕を任意の角度に曲げて角度推定開始
3. 上腕と前腕部のテンプレート画像から腕の状態の候補となる合成画像を生成
4. 角度推定を開始したときのフレーム画像と3の合成画像を肌色抽出し、2値化
5. 4で生成した二枚の画像でテンプレートマッチングし類似度計算
6. 3で肘関節、肩関節の角度を変えながら3~5を繰り返す
7. 最も類似度が高かった時の合成画像の状態を推定結果として出力
となっています。実際の画像で見ていきましょう↓
1. 上腕と前腕部分をテンプレート画像として抽出
マウスドラッグで赤色の枠を出し、画像切り出し部分を選択します。
切り出した画像が↓
2. 腕を任意の角度に曲げて角度推定開始
適当に腕を曲げて角度推定開始です。今回、角度推定開始はキーボードのpキーを押したら始まるようにしました。
3. 上腕と前腕部のテンプレート画像から腕の状態の候補となる合成画像を生成
一度、上腕に対して前腕部を回転させた画像を生成し、その画像全体を回転させています。その結果の合成画像が↓
前腕部回転により肘の回転、そのあとの画像全体の回転によって肩の回転の候補を作成しています。
4. 角度推定を開始したときのフレーム画像と3の合成画像を肌色抽出し、2値化
合成画像に対して肌色領域抽出して2値化したものです↓
5. 4で生成した二枚の画像でテンプレートマッチングし類似度計算
6. 3で肘関節、肩関節の角度を変えながら3~5を繰り返す
7. 最も類似度が高かった時の合成画像の状態を推定結果として出力
プログラム
以上のことをプログラミングしたのが↓
Visual Studio、C++、OpenCVで実現しています
今回は腕の肩側が左側に、手のひら側が右側でカメラに映るのを前提にしています。
動かしてみる
RGBカメラによる人間の関節角度推定ができた(^o^)/ pic.twitter.com/3EGoWmDUtF
— IKEP (@CreativeIKEP) 2018年7月17日
コンソールに出力されてる文字が見にくいですが…
肘関節角度は肘の開き具合です。肘を曲げずに腕がまっすぐなら180度、完全に曲げたら10度(?)です。
肩関節は腕を水平にしている状態が0度、そこから下に降ろした状態が-90度、上にあげた状態が90度です。
まとめ
色々試行錯誤して作った結果、そこそこいい感じに推定できているのではないかなと....
ただ、計算速度が遅すぎるのは問題ですが....笑
やっぱ、RGB-Dカメラを使うのが手取り早いです..... (^^;
Swiftによる自作開発アプリの紹介
私が自作&現在リリースしているアプリを紹介していなかったのでこのブログでも紹介しておきます。
プログラミングを始めて間もない頃に作ったものですので、2年弱前(?)くらいのものかと....。IKEPはApple信者であることもあり、その頃からSwiftを勉強してiPhone用とMac用を1つずつ作りました。
それがこちら↓
iOSアプリはこちら↓
2つとも自分が使いたいからという理由で作りました(笑)
EyeBreakTimerはこの頃開発のためにPCを触る時間が増えたことによって、時間を忘れて作業してしまうのを防ぐために作りました。作業を邪魔しないことが大前提になっているため、ステータスバーでの表示とMacのスリープとの連携によって全自動化を図りました。
BinaryCalculatorは大学の授業課題(宿題)の中で2進数などを扱うことが多々あった時期に、サボるために作りました(笑)
よかったらダウンロードして使ってください(^_^)/
余談
AppStoreへのリリースは日本では20歳にならないとできないと知った時は悲しかったです.....。よって20歳になるまで1年近く公開せずに眠っていたのです~~~
また最近、たまたま私のアプリを紹介してくださっているブログ(?)記事を見つけたので載せときます~↓
追記
WindowsバージョンのEyeBreakTimerを作り、リリースしました!
本格的なゲームを作ってみたい ~進捗その1~
今までUnityを色々勉強したり、何か作ってみたりとしてきたが、(Unityを使った制作物で)商品として売り出せるような作品を作ってないなと思い、商品レベルの本格的ゲームを最初から最後まで1人で作ってみるかと思い立った。
そこでどういうゲームにするかを考えたときにちょうど知ったのが、Nintendo Switch「ゼルダの伝説 BREATH OF THE WILD」
販売からかなり時間が経っていましたが、友人から神ゲーと言われて少しやってみると、神ゲーでした 笑
まあ、そんなこんなでこんな神ゲーが作れないかなと.....w
RPGはUnityの勉強で簡単なのは作ったことがあったんで、RPGで作るかと決定。
(RPGゲームの勉強で作ったやつ~↓)
で、とりあえずRPGで方向は固まったんで、アイデア出しをしてどんなゲームにするかは自分の中では決めました。(細かいことを変更するかもなんで、まだ内緒...)
プラットフォームとしてはPCとスマホの両方を考えています。
ゼロから開始して1ヶ月ほどでこんな感じ(スマホ版収録)↓
最初の1ヶ月はステージ作成と移動制御関連ばっかだったような.....
で、さらに1ヶ月(制作2ヶ月目)ほどでこんな感じ(PC版)↓
だいぶ発展しました。ジャンプや泳ぐのができるようになり、敵の種類も増え攻撃してくるようになりました。最後のワープはエフェクトだけ作りました(ゼルダBotWのワープシーンのマネですw)。
UnityプロジェクトがGithubにあげれなかったのでスクリプトだけ(随時更新します)
以上、進捗その1でした。これからもたまに進捗書くと思いますので、またその時に~
Processingを使ったインタラクティブコンテンツ作品 with OpenCV, ARToolKit
大学での実習を通して、Processingを使ったインタラクティブコンテンツを作成しました。
Processingを使うのは初めてという中で、ある程度形になったものをここに上げておきたいと思います。
(課題提出締め切りギリギリまで制作していたので、ソースコードは汚いです.... m(_ _)m)
画像処理インタラクティブコンテンツ
カメラ入力を使ったインタラクティブコンテンツを作成せよ、と言う課題が出されました。
そこで私はOpenCVでの画像処理を組み込んだコンテンツを作成しました。
完成品はこちら↓
大学の授業課題で作ったものですが、ハンドトラッキングのアルゴリズムがなかなか精度よくできたので...
— IKEP (@CreativeIKEP) 2018年5月10日
processingとopencvで作りました。
言語はJavaです
(深度センサー付ではない普通のカメラです)#Processing #opencv #画像処理 pic.twitter.com/1UX02157Jq
モグラたたきです。カメラを机に向けて設置して、机の映像に対応した部分を叩くとモグラを叩くことができます。アルゴリズムを試行錯誤したら、手が早く動いてもトラッキングの精度が落ちないようにできました。
OpenCVでは顔認識はデフォルトで簡単に行えるようになっているのですが、手形状認識はできません。そこで、手形状認識をしてバーチャルなものに触れることができるものを作ろうと思いました。
普通のRGBのwebカメラで映像を取得し、HSVでの肌色抽出で実現しました。この肌色領域を取得して、その領域とモグラのCGが接触したらモグラを叩いたと認識させています。
ARToolKitを使ったオブジェクトの3次元制御ARシステム
次にARToolKitを使ったARインタラクティブシステムを作成せよ、という課題が出されました。
ARToolKitはARマーカーを使って仮想オブジェクトを表示します。しかし、マーカーをオブジェクト表示だけに使うだけではつまらないと思い、コントローラとして使おうと考えました。
完成品はこちら↓
大学の課題で作ったものですが...
— IKEP (@CreativeIKEP) 2018年6月29日
ARToolKitを使ったインタラクティブキャラクターコントロールシステム
ARToolKitとprocessingでマーカー回転角度を取得して、アフィン変換で実現しました。 pic.twitter.com/8Eg1mvebgE
マーカーを手で隠したり見せたりする事でボタンとしての機能を持たせつつ、マーカーの回転角度をアフィン行列で取得。その中から平面に対して垂直な軸を中心とした回転角度を抽出し(その他の軸の無駄な回転角度を削る)、この角度を使ってオブジェクトをアフィン変換しています。
回転軸切り替えをした時に、オブジェクトに適応しているアフィン行列を今までの変換行列に掛け合わせることで、今までの回転操作の状態を保存したまま異なる回転軸でさらに操作を行えるようにしました(線形代数学ちゃんと勉強しといてよかった…(^^))
感想
普段、Unityの方をメインで使うんでProcessingはあまりやった事なかったですが、やってみると面白かったのでもっと勉強したいですね(^_^)
なによりも描画関係がすごく簡単にできるのが衝撃的でした。
追記
最終課題で、上記のことを全部混ぜたレーシングカーゲームを作りました。ARマーカーの回転角度で車を操作、手認識とオブジェクトへの接触判定でスピードアップです。
ついでにランキング機能を組み込みました。ランキングの順位は、(速くゴールする)>(遅くゴールする)>(ゴールできなか ったときの走行距離⻑)>(ゴールできなかったときの走行距離短)の順です。
完成品はこんな感じです↓。昔のゲームによくある8ビット風の世界です♪
PC内蔵のカメラを使っているので、映像の精度が悪いです....
工夫点としては、
・「ゴールできないかもしれないリスクを背負うが、スピードアップして走行距離をかせぐ」か「走行時間は遅くなるが、着実にゴールするのを狙う」など、ユーザの判断によって、ユーザ個人個人の楽しみ方を自然に提供したところ
・ARマーカー、画像処理による操作をインタラクティブかつ直感的なものになるよう設計
などですね
ただ、自分がunityでの制作に慣れたせいか、シーンの切り替えがprocessingではやりにくいなと感じました 笑
AfterEffects, PhotoShopでVFX、アニメーション動画制作
今回はプログラミング関連ではなく、Adobeで映像制作をした時のゆる〜いお話です。
VFX制作
大学生になって初めてPCを購入し、本格的な映像制作ができる環境になり早速Adobeをはじめました。で、VFXというかっこいいジャンルを知り、何もないところからmacが出てくるVFXを作りました。
素材は二枚の写真
全く同じ構図でmacを置いた写真とと置いていない写真です。
まずはphotoshopで加工〜
macを部品ごとに分解します。
最終的には、キーボード、トラックパッド、ディスプレイ、USB差し込み口、本体上部・下部、アイコン、ステータスバーに分解しました。
この分解したのをAfterEffectsで動きをつければ完成です。
(作ったのが2年前でなので制作中のスクショが残っていません.....)
アニメーション制作
しばらくしてアニメーション映画「君の名は。」で一大ブームを起こしました。Youtubeでは、 実写で予告編を再現してみた動画が流行りました。そこで僕は大学キャンパスの風景を使ったアニメーションの予告編を作ってみました(笑)
今回は正式な予告を真似てみたものです。正式予告はこちら
キャンパスを歩き回って写真を撮り、その写真を「君の名は。」風に加工し、AfterEffectsの下準備。例えば↓
↑これをAfterEffectsで動かすために雲を切り取り、欠損部分を修正↓
編集様子(1万倍速?)↓
で、完成品がこちら↓
おまけ「なぜ映像制作をしていたのか」
僕は幼稚園から高校生までずっとサッカーをしていました。中学生の頃、自分たちの試合の分析や敵チームの傾向分析などのために、カメラで試合の動画を撮ることがありました。その時に撮り方がうまいと言われ、映像に興味を持ちました。(単純w)
そこで、映像音響についての勉強ができる今の大学に行きました。しかし、大学に入ってプログラミングに触れ、映像以外のモノづくりにもハマりました。つまり、僕にとって映像制作は今の僕の原点なのです(笑)
Unity&Blenderによるキャラクターアニメーション 〜モデリングからアニメーション、表情つけ、物理判定まで〜
Unityでゲームとかを作るとなると必ずと言ってもいいほど、必要なのはキャラクター。そのキャラクターのアニメーションはゲームの面白さや完成度を左右すると言っても過言ではないと思います。しかし、Unityのアニメーション関連を説明している書籍やサイトはあまりないように思います。アニメーションよりプログラムなどの動作関連に重視しすぎな感じが.....
そこで今回は、私が今までいろいろキャラクターアニメーション関連でいじってきた小ネタたちをまとめて載せておきたいと思います。興味があるとこだけ見ていただいたら良いかと思います......
Blenderによるキャラクターモデリング
僕はモデリングよりはUnityとかでのプログラミングの方が専門ですが、Unityで自作キャラクターを動かして見たいと思って、作りました。
こちらの方の記事を参考にして作りました。
非常にわかりやすいので、作り方はここでは割愛。
制作中の様子だけ↓
5時間くらいかけてやっとこんだけ
— IKEP (@CreativeIKEP) August 7, 2017
さて、何を作ってるのでしょう? 笑#Blender #3Dモデリング #3DCG pic.twitter.com/qQ7Q8xWIVS
3DCGモデリング、とりあえず頭は完成♪#Blender #3DCG #モデリング #Unity pic.twitter.com/5NMqct5zWB
— IKEP (@CreativeIKEP) August 7, 2017
胴体と腕完成
— IKEP (@CreativeIKEP) August 10, 2017
あとは手と足 pic.twitter.com/rG2Wg1W4L9
完成♪#3DCGモデリング #Blender pic.twitter.com/9OWtcXZrHx
— IKEP (@CreativeIKEP) August 13, 2017
UnityにこのBlenderデータをそのまま取り込み、アニメーションをつける(アニメーションの付け方は↓で)。せっかくなんでARでやって見ました。
アニメーション制作方法
モデルが用意できたらアニメーションをつけます。
まず、モデルのボーンをUnityで適用させる
UnityにインポートしたモデルのInspectorの画面からRigを選択=>Configure...を選択
自動的にボーンが適用されます↓
もし、適用できていないところがあれば赤く表示されるのでその部分は修正します。
適用されない主な原因としては、「モデルがT字ポーズになっていない」、「ボーンの階層構造がおかしい」、「必須のボーンが存在しない」などがあげられると思います。
T字ポーズはUnity画面の右下のRotationをいじってT字にしてあげれば解決すると思います。階層構造だとモデリングソフトでボーンの階層構造をUnityが認識する構造にしてあげる必要があります(こちらの記事など参考にすれば良いかと....。動作確認はしてません)。必須ボーンはUnity画面右の図で実線の丸になっているものがそうです。破線は任意なので設定してもしなくても良いです。
そして、アニメーションをつけます。
Animator Controllerを作成してAnimation Clipを配置
この辺のことはググれば出てくるので割愛
Animation Clipを自分で作るならAnimationウィンドウでこんな感じに編集↓
表情つけ
キャラクターの表情をつけていきます。基本的にはAnimationClipの作成と同じで、AnimationClipで体とかを動かすのではなく、顔のBlendShapesの値をAnimtionClipでいじるという感じになります。
自作モデルの場合はモデリングソフトで前準備をしておきます。
Blenderの場合はシェイプキーを設定しておきます。
シェイプキーを設定したモデルをUnityにインポートするとBlendShapesが表示されます。
AnimationClipでこの値を変化させると表情の完成です。
瞬きと笑顔をつけてみました。瞬きをつけるだけで、無表情の時よりリアルさがグッと増します(^_^)
物理判定
物理判定といっても、キャラクターの服や髪、体などのキャラクターの部品同士の物理判定です。
まず、最初にこれらを考慮しなかった時がこちら↓
ミクさんに現実世界で踊って頂くことにやっと成功した(^^)
— IKEP (@CreativeIKEP) November 5, 2017
(動画長すぎるので一部抜粋)#Unity #ARKit #miku pic.twitter.com/P37aNAQQZC
髪が硬いままだったり、髪やスカートが体に食い込んでしまってます.....。
これを改善していきます。
まず、体の各部位にColliderを設定
そして、スカートにClothを設定。これだけでスカートがなびく感じが出ます。
スカートとの接触するもの部位のcolliderを教えてあげます。
同じく、髪の毛も設定していきます。
髪のなびく感じにもClouthを使いました。髪の毛の動く範囲も決めます。
ClouthのEditConstraintsを選択
頭皮の部分(赤い点)を選択してMaxDistanceを0にします(これをしないと髪の毛が落ちていくw)。それ以外のところはMaxDistanceを任意の値にします。
これで物理判定は完了です。
さっきと比べると、かなりリアルさが出たと思います。(ARで動画を撮りたかったですが、iPhoneで動かすと重たくて動きがカクカクしたので、Unity上で動かしてます)
感想
ヒマな時にこれらを小ネタとしてやっていましたが、これら全部を組み合わせてゲームとかを作るのは大変だなと思いました。しかし、頑張って組み込めば(アニメーションの点では)ゲームのクオリティは上がると思います。
今制作中のゲームにも頑張って組み込むか.....
ただ、モデリングはもうやりたくないかな 笑
おまけ
最近、いろいろ勉強したのを使って任天堂スイッチ「ゼルダの伝説 ブレス オブ ザ ワイルド」のワープシーンを作ってみました。(アニメーションだけでなく、パーティクルの勉強もいるが...)
Nintendo Switchの「ゼルダの伝説 ブレス オブ ザ ワイルド」のワープシーンを作ってみた
— IKEP (@CreativeIKEP) 2018年6月12日
短時間でした割にはそこそこいけてる?? 笑#Nintendo #ニンテンドースイッチ #ゼルダの伝説 #Unity pic.twitter.com/nLHtGnBWpk
GoogleHomeアプリ改良編 ~Cloud Functionsを組み込む~
以前の記事でGoogleHomeを使った機材貸出返却システムを作成したことを書きました。(まだ、見てない方はこちらからどうぞ)
今回はこれの改良を行ったときのことについて書きます。
改良点
今までのシステムはGoogleHomeに「〜貸出!」という感じに話しかけると、Action on Google=>Dialogflow=>GoogleAppsScript(GAS)=>IFTTT(Webhooks)=>LINE通知という流れの処理でした。GASにデータを書き込んで、その処理結果をLINEに送って通知する形です。しかし、本来はGASからの結果をGoogleHomeに喋らせたかったのですが、GASからのJSONでのリターンはリダイレクトされるのでDialogflowでは受け取れないためにLINE通知という方法を仕方なく行っていました。(詳しくはこちら)
そこで今回はDialogflowとGASの間にサーバーをかまして、この問題を解決しました。私はGoogle Cloud Functionsを使いました。ネットでググるとAWSを使っているのが多いみたいなんで参考になれば幸いです( ̄∇ ̄)
Google Cloud Functionsとは
Google Cloud FunctionsはGoogleが提供するGoogle Cloud Platformの1つであり、JavaScriptで書かれた関数を実行するサービスです。関数はイベントによって発火されます。そのイベントの中にHTTPトリガーがあるため、HTTPリクエストがあった時に指定の処理を行うことができます。
今回はこの「指定の処理」が「DialogflowからのデータをGASに送り、GASからの処理結果をDialogflowにリターンする」というものです。
Google Cloud Functions導入
では、Google Cloud Functionsを触っていきます。
プロジェクトを作成したら、↓が表示されるのでAPIを有効にします。
次に関数を作成します。
関数の設定は↓のような感じ。今回はDialogflowからのリクエストを受け取るので、トリガーはHTTPトリガーにする。ここに表示されるURLがトリガーになります。
そして、コードはこんな感じ↓(右から左に流すだけです(^_^;))
index.js
package.json
あとは、dialogflowのwebhook先を先ほどのcloud FunctionsのURLに書き換えれば完成!
完成
完成形がこちら↓
前作ったサークル用の機材管理GoogleHomeアプリを改良しました。
— IKEP (@CreativeIKEP) 2018年5月27日
DialogflowとGoogle Apps Scriptの間にサーバー(Google Cloud Functions)をかますことで処理に応じた回答をGoogleHomeに喋らすことに成功したー!
サーバー関連、一切やったことなかったから苦労したε-(´∀`; )#googlehome pic.twitter.com/ubO4DA7kBr
すでに貸出中の物品ならエラーと言ったり、貸出完了なら返却期限を言ったりと、処理に応じた結果をGoogleHomeから喋らせれました!! (^o^)/
苦労したこと
DialogflowとGASの間にCloud FunctionsをかますことでGASからのJSONリターンのリダイレクトを防ぐようにしましたが、プログラムを書いてる時に気づいたことが.....
それは「Cloud FunctionsからGASヘのデータ送信をPOSTにすると、リダイレクトされる」ということです。これに気づくのにだいぶ時間を使いました。そのため、Cloud FunctionsからGASへはGET送信にして、GAS側もPOST受け付けからGET受け付けに変更しました。
これで理想のシステムが完成しました!
あとは喋っている人の認識かな.....
追記(2018/6/14)
誰が喋っているかの認識もできました!
Dialogflowから送られるJSONデータ内のuserIdで識別しています。GoogleHomeのVoiceMatchに登録されてる声はuserIdが変わらないので、これで喋ってる人を識別できます。
GoogleHomeアプリで話してる人の判別ができた〜!!
— IKEP (@CreativeIKEP) 2018年6月14日
自分の声だとシステムに書き込みできるが、違う人の声(今回は自作の合成音声ソフトの声)だとはじかれる
これで学籍番号を声で言ってたのを省けるようになった^_^#GoogleHome pic.twitter.com/kevuMJFPBN
(僕のGoogleHomeは、僕の声しか登録してないので他人の声は合成音声ソフトで代行しています。)