reComputer-RK / Docker / RKNN / YOLO に基づくビジュアルフィルタデモ

プロジェクト概要
本プロジェクトは 9 種類のフィルタを一つの FILTER_LIST 辞書に集約し、容易に拡張できるようにしています。これにより、191 行のフィルタ専用スタジオを実現しています: gesture.py が両手ピンチを検出 → filter_game.FilterGame が四角形の頂点を維持 → filters.apply_filter が ROI のピクセルを処理します。

クイックスタート
1. リポジトリのクローンとディレクトリ移動
git clone https://github.com/doublelf/filter_game
cd filter_game2. 依存関係のインストール
pip install -r requirements.txtrequirements.txt には次の 4 つの依存関係が固定されています:
opencv-python>=4.8.0
mediapipe>=0.10.14
numpy>=1.26.0
Pillow>=10.4.09 種類のフィルタのうち、EMBOSS / CONTOUR / POSTERIZE は Pillow が提供します。INVERT / NEON / GRAY / SEPIA / HUE_SHIFT / PIXELATE は OpenCV + NumPy で実装されており、Pillow がなくても動作します(Pillow がない場合は元画像を返します。
filters.py:36の_pil_filter_safeを参照)。
3. ゲーム起動
python main.py # デフォルトはカメラ 0、水平反転を有効
python main.py --cam 1 # 2 台目のカメラを使用
python main.py --no-flip # 水平反転を無効化
python main.py --no-landmarks # キーポイントオーバーレイを無効化(デフォルトは有効)
python main.py --hide-trails # ジェスチャートレイルを無効化(デフォルトは有効)起動すると最初に「Filter Studio」メニュー画面が表示され、いずれかのキーを押すとゲームが始まります。
4. 操作方法
| 操作 | プレイヤーの入力 | プログラムの反応 |
|---|---|---|
| 片手でピンチ | 任意の手がピンチを開始 | 人差し指先端にゴールドの拡散リング |
| 両手でピンチ | 両手が同時にピンチ | 両方のアンカーの中点に拡散リング + トースト CONNECTED |
| ピンチ維持 + 移動 | 両手をドラッグ | 四角形 (anchor_l, anchor_r, current_l, current_r) 内部のピクセルに現在のフィルタを適用 |
| 片手を離す | 片手を離す | 四角形が消え、IDLE に戻る |
| 横スワイプでフィルタ切替 | ピンチしていない任意の手で画面を横切るようにスワイプ | SwipeIndicator のサイドグラデーション帯 + トースト Filter N/9 NAME |
| キーボードでフィルタ切替 | 1–9 で直接 / [ ] または , . で次/前 | トースト Filter N/9 NAME |
| いつでも | M でメニューに戻る | カメラはキャプチャを継続、ゲームループのみ終了 |
| いつでも | ESC で終了 | カメラを解放、MediaPipe を閉じ、ウィンドウを破棄 |
カメラなし環境での実行
recomputer-rk3576-devkit は工場出荷時に USB カメラが接続されていません。本プロジェクトは、カメラなしでもエンドツーエンドで動作するように 3 つのツールを同梱しています:
tools/verify_all.py — 8 ステップ検証スイート
cd /home/seeed/hand/filter_game
python3 -m tools.verify_all各ステップを出力します:
- モジュールのインポート (
gesture/filter_game/filters/overlay/utils) utilsのジオメトリ・テキストヘルパー- 9 種類すべてのフィルタが正しい shape と dtype を出力
FilterGameのステートマシン +SwipeTrackerの横スワイプ検出- aarch64 上で本物の MediaPipe Hand Landmarker がロードされる(XNNPACK delegate、約 110 ms のウォームアップ)
HandOverlay.add_event+ レンダリング (both_connected/filter_switch/swipe)- 合成された両手パイプラインが 120 フレームで完走し、FilterGame が少なくとも一度 BOTH_PINCH に到達する
tools/run_synthetic.py — オフラインレンダリング (PNG)
python3 -m tools.run_synthetic --frames 200 --out /tmp/filter_demo
ls /tmp/filter_demo | wc -l # → 200完全な FilterGame + HandOverlay パイプラインを駆動し、次を出力します:
events total=N by_type={'both_connected': 1, ...}
BOTH_PINCH frames: 1 DRAG frames: 146各フレームを out/filter_XXXX.png に書き出します。カメラがない環境では、ffmpeg で mp4 に連結します:
ffmpeg -framerate 30 -i /tmp/filter_demo/filter_%04d.png -c:v libx264 -pix_fmt yuv420p filter.mp4tools/synthetic_source.py + tools/fake_tracker.py
合成ビデオソースと合成 HandTracker で、cv2.VideoCapture / gesture.HandTracker とインターフェース等価です。後で本物のカメラに切り替えるには、次の 2 行を置き換えるだけです:
cap = cv2.VideoCapture(args.cam) # SyntheticHandSource を置き換え
tracker = HandTracker(num_hands=2) # SyntheticHandTracker を置き換えこれで tools/run_synthetic.py が本物のカメラドライバスクリプトに昇格します。