Nota da OP:
Ho accettato questa risposta in quanto è il metodo migliore si può ottenere utilizzando OpenCV,
ma credo che la soluzione migliore in questo caso sta andando per una funzione personalizzata.
Sì, è NORM_L2SQR
:
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
vector<Point> pts{ Point(0, 2) };
double n = norm(pts, NORM_L2SQR);
// n is 4
return 0;
}
Si può vedere nella funzione cv::norm
in stat.cpp
che se si utilizza NORM_L2SQR
non si calcola il sqrt
sulla norma:
...
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;
}
...
Riguardo al problema specifico:
Il mio problema reale è: ho un vettore di punti, unire punti più vicini tra loro di una determinata distanza. "Unire" significa rimuoverne uno e spostare l'altro a metà strada verso il punto appena rimosso.
Probabilmente si può
- approfittare della funzione partition con un predicato che restituisce
true
se due punti sono all'interno di una determinata soglia.
- recuperare tutti i punti nello stesso cluster
- calcolare il baricentro per ogni cluster
Ecco il codice:
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
vector<Point> 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<int> 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<vector<Point>> clusters(n);
for (int i = 0; i < pts.size(); ++i)
{
clusters[labels[i]].push_back(pts[i]);
}
// Compute the centroid for each cluster
vector<Point2f> centers;
for (const vector<Point>& cluster : clusters)
{
// Compute centroid
Point2f c(0.f,0.f);
for (const Point& p : cluster)
{
c.x += p.x;
c.y += p.y;
}
c.x /= cluster.size();
c.y /= cluster.size();
centers.push_back(c);
}
return 0;
}
produrrà i due centri:
centers[0] : Point2f(1.0, 1.3333);
centers[1] : Point2f(10.5, 11.5)
Oh, wow, dove è documentato? – Antonio
Non lo so davvero. Basta guardare attraverso il codice sorgente ... Vedo se trovo una documentazione per questo ... – Miki
Uhm, questo richiede la creazione di un vettore che sembra eccessivo. – Antonio