简体   繁体   中英

using opencv norm function to get euclidean distance of two points

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 ab works well.
The opencv norm function given here .

Note that, sqrt( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) ) 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 .

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 (ie: sqrt( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) ) . It seems harsh, but you can rely on the compiler to optimize that.

As an alternative you can use:

#include <cmath>  // hypot

std::hypot((a - b).x, (a - b).y);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM