Daniel
Daniel

Reputation: 2295

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

Upvotes: 5

Views: 28619

Answers (3)

orbit
orbit

Reputation: 182

As an alternative you can use:

#include <cmath>  // hypot

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

Upvotes: 0

darda
darda

Reputation: 4172

Note that, sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ) 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.

Upvotes: 2

kebs
kebs

Reputation: 6707

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 (i.e.: sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ). It seems harsh, but you can rely on the compiler to optimize that.

Upvotes: 1

Related Questions