【发布时间】:2015-10-01 12:30:49
【问题描述】:
我必须根据距离阈值检查点之间的几个距离。我能做的就是取阈值的平方并将其与(a-b) 的平方范数进行比较,其中a 和b 是我要检查的点。
我知道cv::norm 函数,但我想知道是否存在不计算平方根(因此更快)的版本,或者我是否应该手动实现它。
【问题讨论】:
我必须根据距离阈值检查点之间的几个距离。我能做的就是取阈值的平方并将其与(a-b) 的平方范数进行比较,其中a 和b 是我要检查的点。
我知道cv::norm 函数,但我想知道是否存在不计算平方根(因此更快)的版本,或者我是否应该手动实现它。
【问题讨论】:
OP 的注释:
我接受了这个答案,因为这是使用 OpenCV 可以实现的最佳方法,
但我认为在这种情况下最好的解决方案是使用自定义函数。
是的,是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;
}
您可以在stat.cpp 中的函数cv::norm 中看到,如果您使用NORM_L2SQR,则不会在范数上计算sqrt:
...
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;
}
...
关于具体问题:
我的实际问题是:我有一个点向量,合并点彼此之间的距离比给定距离更近。 “合并”是指移除一个并将另一半移向刚刚移除的点。
你应该可以
true。 代码如下:
#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;
}
将产生两个中心:
centers[0] : Point2f(1.0, 1.3333);
centers[1] : Point2f(10.5, 11.5)
【讨论】:
cv::norm 接受 InputArray。您的积分是如何存储的?
normL2Sqr,它需要一个点作为输入。
partition 的好机会@:D
似乎没有什么专门解决这个问题的。
我认为一种解决方案可能是使用ddot 方法(点积),并计算类似
cv::Point distVec = a-b;
double squaredNorm = distVec.ddot(distVec);
如果愿意冒险,cv::normL2Sqr 要求输入为数组格式:cv::Point 可能直接转换为 int[]。
我将亲自编写我自己的平方范数。
【讨论】: