【问题标题】:Does OpenCV offer a squared norm function for cv::Point?OpenCV 是否为 cv::Point 提供平方范数函数?
【发布时间】:2015-10-01 12:30:49
【问题描述】:

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

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

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    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;
    }
    ...
    

    关于具体问题:

    我的实际问题是:我有一个点向量,合并点彼此之间的距离比给定距离更近。 “合并”是指移除一个并将另一半移向刚刚移除的点。

    你应该可以

    • 利用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)
    

    【讨论】:

    • 其实我也不知道。只是查看源代码...我看看我是否找到了这方面的文档...
    • 呃,这需要创建一个矢量看起来有点过头了。
    • 那只是为了展示用法。 cv::norm 接受 InputArray。您的积分是如何存储的?
    • 我的实际问题是:我有一个点向量,合并点彼此之间的距离比给定距离更近。 “合并”是指移除一个并将另一半移向刚刚移除的点。我需要一个简单的normL2Sqr,它需要一个点作为输入。
    • @Antornio 好吧,这仍然是一个学习如何使用partition 的好机会@:D
    【解决方案2】:

    似乎没有什么专门解决这个问题的。

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

    cv::Point distVec = a-b;
    double squaredNorm = distVec.ddot(distVec);
    

    如果愿意冒险,cv::normL2Sqr 要求输入为数组格式:cv::Point 可能直接转换为 int[]

    我将亲自编写我自己的平方范数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多