【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. 次回

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