Reputation: 2295
The test code is simple:
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
cv::Point2f a(0.f, 1.f);
cv::Point2f b(3.f, 5.f);
std::cout << cv::norm(a - b)<< std::endl;
return 0;
}
It works fine. But if I change the line
std::cout << cv::norm(a - b)<< std::endl;
to std::cout << cv::norm(a, b)<< std::endl;
or std::cout << cv::norm(a - b, cv::NORM_L2)<< std::endl;
error occurs and it tells me that such function cannot be matched.
I don't understand why Point2f
type cannot be converted since the only input parameter a-b
works well.
The opencv norm function given here.
Upvotes: 5
Views: 28619
Reputation: 182
As an alternative you can use:
#include <cmath> // hypot
std::hypot((a - b).x, (a - b).y);
Upvotes: 0
Reputation: 4172
Note that, sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) )
is the same as saying sqrt( (a - b).x * (a - b).x + (a - b).y * (a - b).y )
, so you can call cv::norm(a - b)
.
However, according to this (albeit old) link, performance is poor for single point pairs.
I just ran the test code on my machine. It generates 15,000 points and calculates the distance from each to the remaining points.
a : [0, 0] - b : [2.14748e+09, 2.14748e+09]
euclideanDist : 3.037e+09
distanceBtwPoints : 3.037e+09
cv::norm : 3.037e+09
max_distance euclideanDist : 3.02456e+09 time passed :0.165179
max_distance distanceBtwPoints : 3.02456e+09 time passed :0.259471
max_distance cv::norm : 3.02456e+09 time passed :0.26728
Surprising. The fastest code is
float euclideanDist(cv::Point2f& a, cv::Point2f& b)
{
cv::Point2f diff = a - b;
return cv::sqrt(diff.x*diff.x + diff.y*diff.y);
}
Using cv::norm(a - b)
and the code below are nearly equal:
static double distanceBtwPoints(const cv::Point2f &a, const cv::Point2f &b)
{
double xDiff = a.x - b.x;
double yDiff = a.y - b.y;
return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}
But that's evidently because of the casts to double
. If left as float
, distanceBtwPoints
is as fast as eucledianDist
.
Upvotes: 2
Reputation: 6707
As you can read in the doc, the norm()
set of functions all operate on the generic InputArray
datatype. So, from here, you can see that this can be either a cv::Mat
or std::vector
but certainly not cv::Point2f
.
After checking in the sources (of 3.0, but I doubt it was different in 2.4 series), I see that that function has 9 overloads, but the only ones with cv::Point<>
only have one argument.
So you will need to to convert your points to cv::Mat
. This can be done easily, as there is a constructor for cv::Mat
that takes a point as argument. So just do:
std::cout << cv::norm( cv::Mat(a), cv::Mat(b) ) << std::endl;
But as a side comment, I am not sure that this is the best solution: it implies additional memory allocation, and it is probably faster to compute the distance directly (i.e.: sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) )
. It seems harsh, but you can rely on the compiler to optimize that.
Upvotes: 1