William Zhang2026-09-27

Démo 9 filtres à pincement bimanuel avec MediaPipe Hand Landmarker

Détection en temps réel de 21 points-clés de la main et de l'état de pincement des deux mains sur CPU (accélérée par XNNPACK) à l'aide du modèle MediaPipe Tasks Hand Landmarker. « Les deux mains pincent en même temps » est directement mappé sur une ROI quadrilatérale, et 9 filtres d'image sont appliqués en direct aux pixels contenus dans la ROI.

CVHand TrackingMediaPipeGithub

Démonstration de filtres visuels basée sur reComputer-RK / Docker / RKNN / YOLO

https://github.com/doublelf/filter_game


Présentation du projet

Ce projet regroupe 9 filtres dans un seul dictionnaire FILTER_LIST pour faciliter l'extension — ce qui donne un studio de 191 lignes, purement dédié aux filtres : gesture.py détecte les pincements bimanuels → filter_game.FilterGame maintient les sommets du quadrilatère → filters.apply_filter traite les pixels de la ROI.


Démarrage rapide

1. Cloner le dépôt et entrer dans le répertoire

bash
git clone https://github.com/doublelf/filter_game
cd filter_game

2. Installer les dépendances

bash
pip install -r requirements.txt

requirements.txt fixe quatre dépendances :

text
opencv-python>=4.8.0
mediapipe>=0.10.14
numpy>=1.26.0
Pillow>=10.4.0

Sur les 9 filtres, EMBOSS / CONTOUR / POSTERIZE sont fournis par Pillow ; INVERT / NEON / GRAY / SEPIA / HUE_SHIFT / PIXELATE sont implémentés avec OpenCV + NumPy et fonctionnent aussi sans Pillow (ils renvoient alors l'image d'origine, voir filters.py:36 _pil_filter_safe).

3. Lancer le jeu

bash
python main.py                  # caméra 0 par défaut, miroir horizontal activé
python main.py --cam 1          # utilise la 2ᵉ caméra
python main.py --no-flip        # désactive le miroir horizontal
python main.py --no-landmarks   # désactive la surcouche de points-clés (activée par défaut)
python main.py --hide-trails    # désactive les traînées de gestes (activées par défaut)

Au lancement, vous verrez d'abord l'écran de menu « Filter Studio » ; appuyez sur n'importe quelle touche pour entrer dans le jeu.

4. Commandes

ActionSaisie du joueurRéponse du programme
Pincement d'une mainN'importe quelle main commence à pincerAnneau d'expansion doré au bout de l'index
Pincement des deux mainsLes deux mains pincent en même tempsAnneau d'expansion au point médian entre les deux ancres + Toast CONNECTED
Maintenir le pincement + bougerFaire glisser les deux mainsQuadrilatère (anchor_l, anchor_r, current_l, current_r), avec le filtre courant appliqué à ses pixels internes
Relâcher une mainLibérer une mainLe quadrilatère disparaît, retour à IDLE
Balayage horizontal pour changer de filtreBalayer l'écran avec n'importe quelle main ne pinçant pasBande dégradée latérale SwipeIndicator + Toast Filter N/9 NAME
Changement de filtre au clavier1–9 saut direct / [ ] ou , . suivant/précédentToast Filter N/9 NAME
À tout momentM retour au menuLa caméra continue de capturer, seule la boucle de jeu est fermée
À tout momentESC quitteLibère la caméra, ferme MediaPipe, détruit la fenêtre

Exécution sans caméra

Le recomputer-rk3576-devkit est livré sans caméra USB connectée par défaut. Ce projet embarque trois utilitaires permettant un fonctionnement de bout en bout même sans caméra :

tools/verify_all.py — suite de vérification en 8 étapes

bash
cd /home/seeed/hand/filter_game
python3 -m tools.verify_all

Imprime chaque étape :

  • Importation des modules (gesture / filter_game / filters / overlay / utils)
  • Fonctions géométriques et texte de utils
  • Les 9 filtres produisent une forme et un dtype corrects
  • Machine à états de FilterGame + détection de balayage horizontal de SwipeTracker
  • Vrai MediaPipe Hand Landmarker chargé sur aarch64 (XNNPACK delegate, ~110 ms d'échauffement)
  • HandOverlay.add_event + rendu (both_connected / filter_switch / swipe)
  • La pipeline bimanuelle synthétisée tourne 120 images, et FilterGame a atteint BOTH_PINCH au moins une fois

tools/run_synthetic.py — rendu hors-ligne en PNG

bash
python3 -m tools.run_synthetic --frames 200 --out /tmp/filter_demo
ls /tmp/filter_demo | wc -l      # → 200

Pilote la pipeline complète FilterGame + HandOverlay et imprime :

Code
events total=N by_type={'both_connected': 1, ...}
BOTH_PINCH frames: 1   DRAG frames: 146

Écrit chaque image dans out/filter_XXXX.png. Dans un environnement sans caméra, assemblez les PNG en mp4 avec ffmpeg :

bash
ffmpeg -framerate 30 -i /tmp/filter_demo/filter_%04d.png -c:v libx264 -pix_fmt yuv420p filter.mp4

tools/synthetic_source.py + tools/fake_tracker.py

Une source vidéo synthétisée et un HandTracker synthétisé, équivalents en interface à cv2.VideoCapture / gesture.HandTracker. Pour basculer plus tard sur une vraie caméra, il vous suffit de remplacer ces deux lignes :

python
cap = cv2.VideoCapture(args.cam)               # remplace SyntheticHandSource
tracker = HandTracker(num_hands=2)              # remplace SyntheticHandTracker

tools/run_synthetic.py devient alors un script pilote à caméra réelle.