I have to check several distances between points against a distance threshold. What I can do is taking the square of my threshold and compare it with the squared norm of (a-b)
, where a
and b
are the points I am checking.
I know about cv::norm
function, but I wonder if there exists a version that doesn't compute the square root (and therefore is faster) or if I should implement it manually.
C++ OpenCV cv::norm()a variety of distance norms between two arrays if two arrays are provided. Norm of a Matrix: There are different norm types for which different norms are calculated. General format for cv::norm():
Vec3b is the abbreviation for "vector with 3 byte entries" Here those byte entries are unsigned char values to represent values between 0 .. 255. Each byte typically represents the intensity of a single color channel, so on default, Vec3b is a single RGB (or better BGR) pixel.
ScalarRepresents a 4-element vector. The type Scalar is widely used in OpenCV for passing pixel values. In this tutorial, we will use it extensively to represent BGR color values (3 parameters). It is not necessary to define the last argument if it is not going to be used.
Note from OP:
I accepted this answer as it's the best method one can achieve using OpenCV,
but I think the best solution in this case is going for a custom function.
Yes, it'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;
}
You can see in the function cv::norm
in stat.cpp
that if you use NORM_L2SQR
you don't compute the sqrt
on the norm:
...
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;
}
...
Regarding the specific issue:
My actual problem is: I have a vector of points, merge points closer to each other than a given distance. "Merging" means remove one and move the other half way towards the just removed point.
You can probably
true
if two points are within a given threshold. Here the code:
#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;
}
will produce the two centers:
centers[0] : Point2f(1.0, 1.3333);
centers[1] : Point2f(10.5, 11.5)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With