测试代码很简单:
#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;
}
它工作正常。但是如果我换线std::cout << cv::norm(a - b)<< std::endl;
到std::cout << cv::norm(a, b)<< std::endl;
或std::cout << cv::norm(a - b, cv::NORM_L2)<< std::endl;
发生错误,它告诉我无法匹配此类功能。
我不明白为什么Point2f
类型无法转换,因为唯一的输入参数a-b
运行良好。
这里给出的 opencv 范数函数。
请注意,sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) )
与说sqrt( (a - b).x * (a - b).x + (a - b).y * (a - b).y )
相同,因此您可以调用 cv::norm(a - b)
。
但是,根据这个(尽管很旧)链接,单点对的性能很差。
我刚刚在我的机器上运行了测试代码。它生成 15,000 个点并计算每个点到其余点的距离。
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
令人 惊讶。最快的代码是
float euclideanDist(cv::Point2f& a, cv::Point2f& b)
{
cv::Point2f diff = a - b;
return cv::sqrt(diff.x*diff.x + diff.y*diff.y);
}
使用 cv::norm(a - b)
和下面的代码几乎相等:
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));
}
但这显然是因为演员阵容要double
。如果保持float
,distanceBtwPoints
的速度与eucledianDist
一样快。
正如您在文档中读到的,norm()
组函数都对泛型InputArray
数据类型进行操作。因此,从这里,您可以看到这可以是cv::Mat
或std::vector
但肯定不是cv::Point2f
。
在检查源代码(3.0 的源代码,但我怀疑它在 2.4 系列中是否不同)后,我看到该函数有 9 个重载,但唯一具有cv::Point<>
重载的只有一个参数。
因此,您需要将您的积分转换为 cv::Mat
.这可以很容易地完成,因为有一个cv::Mat
的构造函数将一个点作为参数。所以只需做:
std::cout << cv::norm( cv::Mat(a), cv::Mat(b) ) << std::endl;
但作为附带评论,我不确定这是最好的解决方案:它意味着额外的内存分配,并且直接计算距离可能更快(即:sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) )
.这看起来很苛刻,但您可以依靠编译器来优化它。
作为替代方案,您可以使用:
#include <cmath> // hypot
std::hypot((a - b).x, (a - b).y);