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
true
si deux points se situent dans un seuil donné. 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é.