gestes_main
gestes_main
¶
Le moteur de gestes : des points articulaires à une intention.
Spatial Mesh, gestes — 25 août 2026. Ce module ne voit pas, ne capture rien et ne parle à personne : il reçoit vingt-et-un points par main et rend un état. C'est délibéré — la fiabilité d'un geste se joue ici, pas dans la caméra, et elle doit se tester sans matériel.
Le §11 du cahier des charges est la règle qui structure tout : ne jamais déclencher une action depuis une seule image. Une main qui passe devant l'objectif produit, pendant deux ou trois images, quelque chose qui ressemble à un poing. C'est ainsi qu'un document part tout seul.
D'où la chaîne : points bruts → normalisation → lissage → mesures → pose → état temporel. Et deux protections que l'expérience impose :
L'hystérésis. Le seuil pour ENTRER dans un état est plus exigeant que celui pour en SORTIR. Sans cela, une main qui hésite à la frontière fait osciller l'état dix fois par seconde.
Le temps de repos. Après un geste reconnu, un délai pendant lequel rien n'est reconnu. Sans lui, ouvrir la main après un « attraper » déclenche immédiatement un « relâcher », puis l'inverse.
Les seuils ne sont pas dispersés dans le code : ils vivent dans un objet, et ils se règlent (§13).
Classes¶
Pose
¶
Bases: str, Enum
Ce qu'une main FAIT sur une image donnée — sans mémoire.
Etat
¶
Bases: str, Enum
Ce que l'utilisateur est en train de faire — avec mémoire (§12).
Seuils
dataclass
¶
Seuils(
confiance_minimale: float = 0.6,
fermeture_entree: float = 1.14,
fermeture_sortie: float = 1.44,
ouverture_entree: float = 1.52,
ouverture_sortie: float = 1.38,
images_stables: int = 4,
trou_de_suivi_ms: int = 400,
repos_ms: int = 800,
lissage: float = 0.4,
)
Tous les nombres qui décident, en un seul endroit (§13).
Aucun de ces nombres n'est magique : ce sont des points de départ raisonnables, à régler sur des vraies mains — et le §141 exige que les faux positifs soient MESURÉS avant de dire que les gestes sont finis.
Mesures
dataclass
¶
Ce qu'on lit d'une main, indépendamment de sa taille et sa distance.
MoteurDeGestes
¶
MoteurDeGestes(seuils: Optional[Seuils] = None)
La machine à états (§12), avec hystérésis et temps de repos.
Une instance suit UNE main. Elle ne connaît ni caméra, ni fichier, ni appareil : elle rend un état, et c'est à l'appelant d'en faire quelque chose — ou rien, ce qui est le cas le plus fréquent et le plus sain.
Source code in src/diapason/desktop/gestes_main.py
Methods:¶
observer
¶
observer(
points: Optional[Sequence[Point]],
*,
maintenant: Optional[float] = None,
) -> Etat
Une image de plus. Rend l'état APRÈS cette image.
points vaut None quand aucune main n'est vue — et c'est une
information, pas une absence d'information : une main qui disparaît
au milieu d'un geste doit l'annuler, jamais le figer.
Source code in src/diapason/desktop/gestes_main.py
Functions:¶
mesurer
¶
mesurer(points: Sequence[Point]) -> Optional[Mesures]
Les mesures d'une main, ou None si elle est trop incomplète.
Tout est rapporté à la largeur de la paume : une main près de l'objectif et une main au fond de la pièce donnent les mêmes nombres. C'est ce qui rend les seuils tenables sans calibration par utilisateur.
Source code in src/diapason/desktop/gestes_main.py
seuils_calibres
¶
seuils_calibres(
repliement_ouvert: float,
repliement_ferme: float,
*,
base: Optional[Seuils] = None,
) -> Seuils
Des seuils dérivés de DEUX mesures réelles, pas d'une supposition.
L'hystérésis occupe le tiers central de l'écart mesuré : assez large pour qu'une main qui hésite ne fasse pas osciller l'état, assez étroite pour que le geste reste franc.
Source code in src/diapason/desktop/gestes_main.py
charger_seuils
¶
charger_seuils() -> Seuils
Les seuils de CETTE machine — ceux d'usine si rien n'est calibré.