OpenCV是否为cv :: Point提供了平方范数函数?

时间:2015-10-01 12:30:50

标签: c++ opencv

我必须检查点之间的几个距离与距离阈值。我可以做的是取我的阈值的平方并将其与(a-b)的平方范数进行比较,其中ab是我正在检查的点。

我知道cv::norm函数,但我想知道是否存在不计算平方根的版本(因此更快)或者我是否应该手动实现它。

2 个答案:

答案 0 :(得分:4)

来自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;
}

您可以在cv::norm中的stat.cpp函数中看到,如果您使用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;
}
...

关于具体问题:

  

我的实际问题是:我有一个点矢量,合并点比给定距离更接近彼此。 &#34;合并&#34;意味着移除一个并将另一半移向刚删除的点。

你可以

  • 如果两个点在给定阈值内,则利用partition函数和谓词返回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)

答案 1 :(得分:0)

似乎有解决这个问题的具体问题。

我认为一个解决方案可能是使用ddot方法(点积),并计算像

这样的东西
cv::Point distVec = a-b;
double squaredNorm = distVec.ddot(distVec);

如果有人愿意承担风险,那么cv::normL2Sqr要求输入采用数组格式:cv::Point可以直接转换为int[]

我将亲自继续写下我自己的平方规范。