web-dev-qa-db-fra.com

OpenCV, C ++: Distance entre deux points

Pour un projet de groupe, nous essayons de créer un jeu, où les fonctions sont exécutées chaque fois qu'un joueur forme un ensemble de gestes spécifiques de la main devant une caméra. Pour traiter les images, nous utilisons Open-CV 2.3.

Pendant le traitement d'image, nous essayons de trouver la longueur entre deux points. Nous savons déjà que cela peut être fait très facilement avec la loi de Pythagore, bien qu'il soit connu que la loi de Pythagore nécessite beaucoup de puissance informatique, et nous souhaitons le faire en utilisant le moins de ressources possible.

Nous souhaitons savoir s'il existe une fonction intégrée dans Open-CV ou une bibliothèque standard pour C++, qui peut gérer les calculs à faible ressource de la distance entre deux points. Nous avons les coordonnées des points, qui sont en valeurs de pixels (bien sûr).

Information supplémentaire: L'expérience précédente nous a appris que OpenCV et d'autres bibliothèques sont fortement optimisés. Par exemple, nous avons tenté de modifier les valeurs RVB du flux d'images en direct de la caméra avec une boucle for, en passant par chaque pixel. Ceci fourni avec une sortie à faible fréquence d'images. Au lieu de cela, nous avons décidé d'utiliser une fonction intégrée Open-CV à la place, ce qui nous a plutôt donné une sortie à fréquence d'images élevée.

15
Marc Pilgaard

Comme vous l'avez correctement souligné, il existe une fonction OpenCV qui fait une partie de votre travail :)

(Vérifiez également dans l'autre sens )

Il s'appelle magnitude () et il calcule la distance pour vous. Et si vous avez un vecteur de plus de 4 vecteurs pour calculer les distances, il utilisera SSE (je pense) pour le rendre plus rapide.

Maintenant, le problème est qu'il ne calcule que le carré des puissances, et vous devez faire les différences à la main. (consultez la documentation). Mais si vous les utilisez également en utilisant les fonctions OpenCV, cela devrait être rapide.

Mat pts1(nPts, 1, CV_8UC2), pts2(nPts, 1, CV_8UC2);
// populate them
Mat diffPts = pts1-pts2;
Mat ptsx, ptsy;
// split your points in x and y vectors. maybe separate them from start
Mat dist;
magnitude(ptsx, ptsy, dist); // voila!

L'autre façon est d'utiliser un sqrt très rapide:

// 15 times faster than the classical float sqrt. 
// Reasonably accurate up to root(32500)
// Source: http://supp.iar.com/FilesPublic/SUPPORT/000419/AN-G-002.pdf

unsigned int root(unsigned int x){
    unsigned int a,b;
    b     = x;
    a = x = 0x3f;
    x     = b/x;
    a = x = (x+a)>>1;
    x     = b/x;
    a = x = (x+a)>>1;
    x     = b/x;
    x     = (x+a)>>1;
    return(x);  
}
20
Sam

Vous devriez essayer ceci

cv::Point a(1, 3);
cv::Point b(5, 6);
double res = cv::norm(a-b);//Euclidian distance
28
Yonatan Simson

Cela devrait faire un commentaire, mais je n'ai pas assez de représentants (50?) | donc je le poste comme réponse.

Ce que les gars essaient de vous dire dans les commentaires de vos questions, c'est que s'il s'agit seulement de --- (comparer distances, alors vous pouvez simplement utiliser d = (dx * dx + dy * dy) = (x1- x2) (x1-x2) + (y1-y2) (y1-y2) évitant ainsi la racine carrée. Mais vous ne pouvez bien sûr pas ignorer l'élévation carrée.

3
kebs

Pythagore est le moyen le plus rapide et ce n'est vraiment pas aussi cher que vous le pensez. C'était le cas, à cause de la racine carrée. Mais les processeurs modernes peuvent généralement le faire en quelques cycles.

Si vous avez vraiment besoin de vitesse, utilisez OpenCL sur la carte graphique pour le traitement d'image.

1
Hannesh