Question

Je construis un Kinect SDK WPF applicaiton et en utilisant le Kinect pour déplacer un "curseur" / objet main.

Le problème que j'ai que 30 images par seconde le curseur est en fait sautiller un peu de façon erratique en raison de la précision du Kinect (c.-à-tout en maintenant votre main encore l'objet se déplace dans un espace 5px).

Je prévois écrire un algorithme qui ne se déplace pas simplement le X / Y de mon « curseur » sprint à la bonne position sur l'écran, mais se comporte plus comme un « déplacer la main vers ce X / Y coordonner » afin qu'il soit un mouvement plus lisse.

point que quelqu'un peut me un bon que quelqu'un d'autre a écrit pour que je puisse éviter de réinventer la roue.

Je comprends que cela est probablement assez commun, mais comme je suis plus d'un développeur d'affaires, je ne suis pas sûr du nom pour une telle fonction si des excuses à l'avance si sa une question n00b.

Était-ce utile?

La solution

Quand je travaillais avec le Kinect, je viens d'utiliser quelques calculs simples (que je pense que l'on appelle la régression linéaire) pour passer à un point à une certaine distance entre la position actuelle du curseur et son emplacement cible. Obtenez l'emplacement du curseur, obtenir l'emplacement est à (traduit en coordonnées d'écran) la main de l'utilisateur, puis déplacez le curseur sur un point entre ceux-ci.

float currentX = ..., currentY = ..., targetX = ..., targetY = ...; 
float diffX = targetX - currentX;
float diffY = targetY - currentY;
float delta = 0.5f; // 0 = no movement, 1 = move directly to target point. 

currentX = currentX + delta * diffX;
currentY = currentY + delta * diffY;

Vous aurez toujours sautillement, selon le delta, mais il sera beaucoup plus lisse et plus généralement dans une zone plus petite.

Sur le même sujet, avez-vous pris un regard sur les paramètres de lissage squelette du Kinect? Vous pouvez effectivement laisser la poignée du SDK certains du filtrage.

Autres conseils

Considérons les valeurs d'entrée (les positions de saut) en tant que signal à la fois bas et des parties à haute fréquence. Les basses fréquences représentent la position grossière / mouvement tandis que les parties à haute fréquence contiennent le saut rapide à des distances plus petites.

Alors, que vous avez besoin ou rechercher est un filtre passe-bas. Qui filtre les pièces de haute fréquence et les feuilles bruts la position (mais aussi précis que Kinect peut obtenir) plus, si vous parvenez à le configurer avec le paramètre droit. Ce paramètre est la fréquence de coupure du filtre. Vous devez jouer un peu et vous verrez.

Un exemple de mise en œuvre des valeurs de temps discret serait ici (à l'origine de wikipedia ):

static final float ALPHA = 0.15f;

protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
        output[i] = output[i] + ALPHA * (input[i] - output[i]);
    }
    return output;
}

Vous pouvez mettre les dernières valeurs des deux composantes X et Y de vos vecteurs de position dans cette fonction pour les lisser (input[0] pour X et input[1] Y, output[0] et output[1] sont des résultats de l'appel de la fonction précédente).

Comme je l'ai déjà dit, il faut trouver un bon équilibre du facteur de lissage ALPHA (0 = = 1 ALPHA) :

  • Trop grand et le signal ne sera pas assez lissée, l'effet ne sera pas en suffisante
  • Trop petit et le signal sera lissée « trop », le curseur en retard sur le mouvement des utilisateurs, trop d'inertie

(Si vous regardez la formule newout = out + alpha * (in - out), vous voyez que, avec une valeur alpha de 0, il vous suffit de prendre l'ancienne valeur de out à nouveau, par conséquent, la valeur ne changera jamais, tandis que d'une valeur de 1 vous avez newout = out + in - out cela signifie que vous Ne lisser tout sauf toujours la valeur la plus récente)

Une idée très simple pour résoudre ce problème serait d'afficher le curseur à un endroit qui est la moyenne d'un certain nombre de positions passé. Par exemple, supposons que vous suivez les cinq derniers emplacements de la main, puis d'afficher le curseur à cette position. Ensuite, si est relativement encore la main de l'utilisateur, les saccades du cadre à cadre doit être raisonnablement bas, parce que les cinq derniers cadres auront eu la main à peu près la même position et le bruit doit annuler. Si l'utilisateur se déplace alors le curseur sur l'écran, le curseur s'animer comme il se déplace de son ancienne position à la nouvelle position, depuis que vous facteur dans les cinq dernières positions de la main la position moyenne va lentement interpoler entre son ancien et le nouveau positions.

Cette approche est très facilement peaufiné. Vous pouvez transformer les points de données afin que les anciens points sont pondérés plus ou moins de nouveaux points, et pourrait ajuster la longueur de l'histoire que vous gardez.

Hope this helps!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top