HoloLens2で音楽ゲームを作った

諸事情で3週間ほど暇になったのでこちらのハッカソンに参加してHoloManiaという音ゲーを作ってみました。
osaka-driven-dev.connpass.com

成果物はこちら

youtu.be


当日の様子はTwitterで "#HoloHack" ハッシュタグで検索すると感じ取っていただけるかと!

空間に花を咲かせた数を競うス○ラトゥーンみたいなゲーム、ソードや銃を出して遊べるUI機能など、面白い作品ぞろいで、HoloLensってこんな遊び方ができるんだ......!とワクワクしながら発表をきいておりました。

実装について

Unity + MRTKプロジェクトのHelloWorldは以下の記事を参考にしました。
qiita.com


Unityのプロジェクト容量が大きすぎてgithubにアップロードできなかったので、かいつまんで説明すると、

  • 一定の周期でGameObjectを生成する
  • 生成したGameObjectをプレイヤーの方に移動させる
  • MRTKでハンドトラッキングしてGameObjectとの衝突を判定する
  • 得点を更新する
  • 一定以上の得点を獲得すればゲームクリア

としました。
リズムに合わせてノーツを生成する、判定ポイントの作成などは実装期間の短さなどから省略した、とてもシンプルなゲームです。

ハッカソン初参加だった

実はハッカソン未経験でした。周囲に迷惑をかけたくないなと思い「ボッチソン」での参加表明をしました。(後から一般的にはハッカソンはチーム戦で得意なところだけ実装してもいいんだよと教えてもらいました......)

初日:アイデア出し
2~8日目:ひたすら実装
9日目:実機にデプロイして動画撮影

のようなスケジュールで実装しました。圧倒的に人手が足りないのがボッチソンのつらいところですね。

HoloLens2は一度だけ触らせてもらったことがある程度で、具体的に何ができるのかほぼ知らない状態、Unity, 3Dプログラミングの経験なし、ということでかなり苦戦しましたが、スタッフの方のヘルプもあり、なんとか9日間の開催期間内で動くものを作ることができました。

今後について

楽曲の著作権などあるのでこちらにパッケージを載せられないのが残念ですが、大阪某所のコミュニティ内でにてひっそりと遊んでいただこうと思っています。

今後もコンテンツをアップデートしていきたいですね。
例えば

  • ランキング機能
  • リズムとノーツのタイミングを合わせる機能

などあるともっと楽しそうです。

賞をいただきました

出場チームが7チームに対して賞が7つあったのですが!うれしいものですね!
ちなみに「ホログラム賞」という賞をいただきました。
反射神経を競うより、シニア向けのゲームにすると面白そう、というコメントも。
自分の作った作品を企業の方にその場で品評していただける機会ってそうそうないと思いますので、もうそれだけでめちゃくちゃ嬉しいですし、頂いたコメントを参考にしてアップデートを重ねていきたいと思います。

スタッフのみなさま、参加者のみなさま、お疲れさまでした。

次のハッカソンはチーム戦で参加したいな......。

MediaPipeとOpenCVで指先から炎エフェクトを出してみる

SNOWのハロウィンスタンプでこんなものを見つけました。

指先からロウソクの炎がゆらゆら......面白いですね!

ということで自分も作ってみました。



いかにも合成!って感じですけど、炎の魔道士っぽいエフェクトができました!

実装

0. 環境

macOS Catalina
OpenCV 4.x.x

1. ファイルを作る

今回はdesktop版のmulti_hand_trackingで作りました。
mediapipe/example/desktop/multi_hand_tracking 直下に新しく.ccファイルを作成します。

また、炎画像の素材を用意します。
自分はUnityの無料アセットから炎エフェクトのtiffを見つけて、
透過pngに切り出して保存し、連番ファイル名を付けました。



2. MediaPipeで指先認識 + OpenCVで炎画像を貼り付ける

全実装は以下。



MediaPipe + OpenCVで指先から炎エフェクトを出す


内容をかいつまんで説明すると、
getCurrentFireImage() で炎画像 (今回は50枚用意しました) を一枚ずつ取り出して、lightFire() 内で指先を判定して1フレームごとに貼り付けています。

実行して上記のデモのように動けば成功です。
おもちゃレベルですが、簡単に実装できますし、遊んでみると結構楽しいものですね。

【MediaPipe + OpenCV】ジェスチャ入力方式のソフトウェアキーボードを作る (2) -ジェスチャ基本入力編-

前回の記事はこちら

ログを出力するところまで出来ている状態です。

今回は「ジェスチャ基本入力編」ということで、
ここからキーボード作成/ジェスチャ入力まで一気に実装していきます。

現状の暫定版demo


実装

全実装は以下。
(制作途中のものです)

続きを読む

【MediaPipe + OpenCV】ジェスチャ入力方式のソフトウェアキーボードを作る (1) -ログ出力編-

何やら巷では自作キーボードなるものが流行っている (?) ようですね。

キー配置や打鍵感など、自分好みにカスタマイズできる自由度の高さが醍醐味の模様。

ここで私も作ってみたいと思い立つものの、ちょうどREALFORCEを購入した直後だったため、「実物」を作ることは断念。代わりにジェスチャ入力で動くソフトウェアキーボードを作ることにしました。


今回は第一弾

ログ出力編」です。

***

1. 現状の暫定版demo


 
精度はまだまだ悪いですが、ジェスチャによるキー選択を実現しています。
(精度改良・未対応キーマップの追加等が出来たらまた記事にする予定です。)
今回はログ出力のみの解説ですので、キーボードの処理などは次回お楽しみに。

 

2. さっそく作る

0. 開発環境

macOS Catalina

VSCode

1. MediaPipeをクローン

こちらからMediaPipeをクローンし、公式サイトの手順通りセットアップを済ませます。

以下のコマンドでdesktop版Hands (multi_hand_tracking)をビルド/実行します。

bazel build -c opt --define MEDIAPIPE_DISABLE_GPU=1 \
mediapipe/examples/desktop/multi_hand_tracking:multi_hand_tracking_cpu 
export GLOG_logtostderr=1 
bazel-bin/mediapipe/examples/desktop/multi_hand_tracking/multi_hand_tracking_cpu \ 
 -calculator_graph_config_file=mediapipe/graphs/hand_tracking/multi_hand_tracking_desktop_live.pbtx

カメラが起動し、両手を認識していればOKです。

2. ログを出す

mediapipe/examples/desktop/multi_hand_tracking以下のBULDファイルを書き換えます。

この部分を、

 cc_binary(
    name = "multi_hand_tracking_cpu",
    deps = [
        "//mediapipe/examples/desktop:demo_run_graph_main",
        "//mediapipe/graphs/hand_tracking:multi_hand_desktop_tflite_calculators",
    ],
)

以下のように変えます。

 cc_binary(
    name = "multi_hand_tracking_cpu",
    srcs = ["multi_hand_tracking_run_graph_cpu_main.cc"],
    deps = [
        "//mediapipe/framework:calculator_framework",
        "//mediapipe/framework/formats:image_frame",
        "//mediapipe/framework/formats:image_frame_opencv",
        "//mediapipe/framework/port:commandlineflags",
        "//mediapipe/framework/port:file_helpers",
        "//mediapipe/framework/port:opencv_highgui",
        "//mediapipe/framework/port:opencv_imgproc",
        "//mediapipe/framework/port:opencv_video",
        "//mediapipe/framework/port:parse_text_proto",
        "//mediapipe/framework/port:status",
        "//mediapipe/graphs/hand_tracking:multi_hand_desktop_tflite_calculators",
    ],
)

さらに、同じディレクトリに新しくmulti_hand_tracking_run_graph_cpu_main.ccを作り、
一つ上の階層 mediapipe/examples/desktop/ の demo_run_graph_main.ccの内容を全てコピーして貼り付けます。

以下のように書いてあるところに、

// Get the packet containing multi_hand_landmarks.
    ::mediapipe::Packet multi_hand_landmarks_packet;
    if (!multi_hand_landmarks_poller.Next(&multi_hand_landmarks_packet)) break;
    const auto& multi_hand_landmarks =
        multi_hand_landmarks_packet.Get<
            std::vector<::mediapipe::NormalizedLandmarkList>>();

以下を追記します。

  LOG(INFO) << "#Multi Hand landmarks: " << multi_hand_landmarks.size();
     int hand_id = 0;
     for (const auto& single_hand_landmarks: multi_hand_landmarks) {
       ++hand_id;
       LOG(INFO) << "Hand [" << hand_id << "]:";
       for (int i = 0; i < single_hand_landmarks.landmark_size(); ++i) {
         const auto& landmark = single_hand_landmarks.landmark(i);
         LOG(INFO) << "\tLandmark [" << i << "]: ("
                   << landmark.x() << ", "
                   << landmark.y() << ", "
                   << landmark.z() << ")";
       }
     }

最後に、以下のコマンドで実行します。

bazel build -c opt --define MEDIAPIPE_DISABLE_GPU=1 \
mediapipe/examples/desktop/multi_hand_tracking:multi_hand_tracking_cpu 
export GLOG_logtostderr=1 
bazel-bin/mediapipe/examples/desktop/multi_hand_tracking/multi_hand_tracking_cpu 

ターミナルにログが出力されていれば成功です。

3. 次回

今回はログを出すところまでなので、記事としてはちょっとしょぼいんですが...。
次回からは実際にキーボード作りや、指のタッチ判定処理などを作っていきますので、ご期待ください。