2017-10-02 6 views
0

Je travaille sur un projet qui prend des données à partir d'un capteur en mouvement. nous avons converti les données du capteur en coordonnées 3D. l'un des capteurs est planté à portée de main de l'objet. PROBLÈME: Lorsque l'objet déplace sa main vers l'arrière, puis joue dans la direction avant. Donc, je cherche le numéro de l'image à laquelle la main de l'objet se termine en arrière.Comment trouver un changement de direction dans un espace 3D

Juste pour résoudre le problème, ce genre de points peut venir en 3D Voici un exemple de données d'image:

img

initialement i mis en œuvre ce, en utilisant un changement dans l'axe y. Avec une valeur seuil, le résultat est bon. Mais seulement lorsque la main de l'objet recule et avance avec la valeur décroissante de l'axe y. Mais dans le cas idéal (l'image), la main peut se manifester de n'importe quelle façon, c'est-à-dire avec une valeur croissante de y ou une valeur décroissante de y. Mais je suis sûr que tout en se déplaçant dans la direction du dos, il y aura toujours des augmentations (à l'exception d'une trame de bruit ou d'une valeur aberrante). en utilisant cela, j'ai mis cela en œuvre. `

std::pair<std::pair<int, int>, bool> calculateBacklift(std::vector<glm::vec3> points) 
{ 
    std::pair<std::pair<int, int>, bool> backlift; 
    backlift.second = false; 
    std::vector<glm::vec3> distanceVec; 
    for (int i = 0; i < points.size() - 1; ++i) 
    { 

     // vector 
     glm::vec3 distance; 
     distance.x = points[i + 1].x - points[i].x; 
     distance.y = points[i + 1].y - points[i].y; 
     distance.z = points[i + 1].z - points[i].z; 
     distanceVec.push_back(distance); 
    } 
    writeTodisk("distanceVector.csv", distanceVec); 
    for (int i = 0; i < distanceVec.size(); ++i) 
    { 

     // y is major axis and if any of x or z hand changed then i am assuming there can be direction change. this comes from experiment. 
     if (distanceVec[i].y <= -0.09 && (distanceVec[i].x <= -0.1 || distanceVec[i].z >= 0.9)) 
     { 
      backlift.first = std::make_pair(1, i + 1); 
      backlift.second = true; 
      break; 
     } 
    } 
    return backlift; 
}` 

Mais cela ne fonctionne pas lorsque la main se lève vers le haut. parce que le changement de l'axe y est positif. Puis je pense à trouver un changement de direction en utilisant le produit scalaire. Et la valeur cos. Mais il détecte également le changement de direction sur l'axe (X, Z). Ou de façon simple, je peux dire que je veux trouver le point de coin dans le déplacement des données du capteur dans la direction de l'axe y (majeur). Quelqu'un peut-il m'aider à résoudre ce problème.

Merci.

+0

Votre question est inintelligible. Vous dites que * back * est + Y, et * forward * peut aussi être + Y, et vous voulez détecter quand on change à l'autre. – Beta

+0

Vous avez besoin d'une heuristique pour déterminer quand le changement de direction (ou de courbure) est significatif. RANSAC est un exemple d'un tel algorithme - il calcule l'ajustement de ligne (presque) optimal pour un ensemble de points de données. – meowgoesthedog

+0

Voulez-vous trouver le "point d'angle" dès qu'il se produit, ou avez-vous toujours le point entier ensemble? – chtz

Répondre

0

En supposant que vous ayez la trajectoire complète du point, je chercherais simplement le point qui a la plus grande distance jusqu'à la ligne reliant le point de départ au point final. Je ne sais pas la bibliothèque de vecteur que vous utilisez, mais en utilisant le Eigen-library ce serait quelque chose comme ceci:

std::vector<Eigen::Vector3f> points; // input set of points 

typedef Eigen::ParametrizedLine<float, 3> Line3; 
// Calculate line through first and last point of points: 
Line3 start_to_end = Line3::Through(points[0], points.back()); 
float max_dist_squared=0.0f; 
size_t max_idx=0; 
for(size_t i=0; i<points.size(); ++i) { 
    // calculate squared (perpendicular) distance from points[i] to the line 
    float dist2 = start_to_end.squaredDistance(points[i]); 
    // check if distance is bigger than previous maximum: 
    if(dist2 > max_dist_squared) { max_dist_squared = dist2; max_idx = i; } 
} 

Vous devriez être en mesure de mettre en œuvre quelque chose d'équivalent à la bibliothèque de votre choix.

Si vous devez gérer des valeurs aberrantes ou du bruit, utilisez une moyenne mobile ou une moyenne mobile plutôt que des points uniques.

+0

J'ai compris votre concept et j'espère que cela fonctionnera bien pour moi. J'utilise la bibliothèque de mathématiques glm (openGL). J'ai essayé d'intégrer Eigen Library et j'ai essayé de compiler votre code. Je n'ai jamais utilisé Eigen et obtenir une erreur dans l'espace de noms Eigen. "Namespace Eigen n'a pas de membre Vector3f". De plus, vector3f ne se trouve pas dans l'espace de noms Eigen. Est-ce que Vector3f existe dans Eigen Namespace? ou je l'ai mal intégré. J'utilise MS2017. – fochka

+0

Si vous voulez utiliser Eigen, lisez le http://eigen.tuxfamily.org/dox/GettingStarted.html Sinon, considérez cela comme un pseudo-code. – chtz

+0

J'ai exécuté le code. Mais ne pas obtenir le résultat attendu. Je voulais juste savoir que squaredDistance() donnerait une distance perpendiculaire à la ligne créée par deux points d'extrémité? ou avons-nous autre méthode pour résoudre ce problème? – fochka