OpenCV offre-t-il une fonction de norme au carré pour cv :: Point?

Je dois vérifier plusieurs distances entre les points par rapport à un seuil de distance. Ce que je peux faire, c’est prendre le carré de mon seuil et le comparer à la norme au carré de (ab) , où a et b sont les points que je vérifie.

Je connais cv::norm function, mais je me demande s’il existe une version qui ne calcule pas la racine carrée (et est donc plus rapide) ou si je devrais l’appliquer manuellement.

Note de l’ OP :
J’ai accepté cette réponse car c’est la meilleure méthode possible avec OpenCV,
mais je pense que la meilleure solution dans ce cas-ci va pour une fonction personnalisée.


Oui, c’est NORM_L2SQR :

 #include  #include  using namespace cv; using namespace std; int main() { vector pts{ Point(0, 2) }; double n = norm(pts, NORM_L2SQR); // n is 4 return 0; } 

Vous pouvez voir dans la fonction cv::norm de stat.cpp que si vous utilisez NORM_L2SQR vous ne calculez pas le sqrt sur la norme:

 ... if( normType == NORM_L2 ) { double result = 0; GET_OPTIMIZED(normL2_32f)(data, 0, &result, (int)len, 1); return std::sqrt(result); } if( normType == NORM_L2SQR ) { double result = 0; GET_OPTIMIZED(normL2_32f)(data, 0, &result, (int)len, 1); return result; } ... 

Concernant le problème spécifique:

Mon problème actuel est le suivant: j’ai un vecteur de points, fusionnant des points plus proches les uns des autres qu’une distance donnée. “Fusionner” signifie en supprimer un et déplacer l’autre à mi-chemin vers le point qui vient d’être supprimé.

Vous pouvez probablement

  • Tirez parti de la fonction de partition avec un prédicat renvoyant la valeur true si deux points se situent dans un seuil donné.
  • récupérer tous les points du même cluster
  • calculer le centroïde pour chaque cluster

Voici le code:

 #include  #include  using namespace cv; using namespace std; int main() { vector pts{ Point(0, 2), Point{ 1, 0 }, Point{ 10, 11 }, Point{11,12}, Point(2,2) }; // Partition according to a threshold int th2 = 9; vector labels; int n = partition(pts, labels, [th2](const Point& lhs, const Point& rhs) { return ((lhs.x - rhs.x)*(lhs.x - rhs.x) + (lhs.y - rhs.y)*(lhs.y - rhs.y)) < th2; }); // Get all the points in each partition vector> clusters(n); for (int i = 0; i < pts.size(); ++i) { clusters[labels[i]].push_back(pts[i]); } // Compute the centroid for each cluster vector centers; for (const vector& cluster : clusters) { // Compute centroid Point2f c(0.f,0.f); for (const Point& p : cluster) { cx += px; cy += py; } cx /= cluster.size(); cy /= cluster.size(); centers.push_back(c); } return 0; } 

produira les deux centres:

 centers[0] : Point2f(1.0, 1.3333); centers[1] : Point2f(10.5, 11.5) 

Il semble qu’il n’y ait rien de spécifique pour résoudre ce problème.

Je pensais qu’une solution pourrait utiliser la méthode ddot (produit scalaire) et calculer quelque chose comme:

 cv::Point distVec = ab; double squaredNorm = distVec.ddot(distVec); 

Si vous êtes prêt à prendre le risque, cv::normL2Sqr requirejs que l’entrée soit au format tableau: cv::Point peut être directement convertible en int[] .

Je vais personnellement passer à autre chose en écrivant ma propre norme au carré.