kookoo121 kookoo121 - 10 months ago 193
C++ Question

How can I calculate the curvature of an extracted contour by opencv?

I did use the

method to extract contour from the image, but I have no idea how to calculate the curvature from a set of contour points. Can somebody help me? Thank you very much!

Answer Source

For me curvature is:

where t is the position inside the contour and x(t) resp. y(t) return the related x resp. y value. See here.

So, according to my definition of curvature, one can implement it this way:

std::vector< cv::Point2f > vecCurvature( vecContourPoints.size() );

cv::Point2f posOld, posOlder;
cv::Point2f f1stDerivative; f2ndDerivative;   
for (size_t i = 0; i < vecContourPoints.size(); i++ )
    const cv::Point2f& pos = vecContourPoints[i];

    if ( i == 0 ){ posOld = posOlder = pos; }

    f1stDerivative.x =   pos.x -        posOld.x;
    f1stDerivative.y =   pos.y -        posOld.y;
    f2ndDerivative.x = - pos.x + 2.0f * posOld.x - posOlder.x;
    f2ndDerivative.y = - pos.y + 2.0f * posOld.y - posOlder.y;

    float curvature2D = 0.0f;
    if ( std::abs(f2ndDerivative.x) > 10e-4 && std::abs(f2ndDerivative.y) > 10e-4 )
        curvature2D = sqrt( std::abs( 
            pow( f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y, 2.0f ) / 
            pow( f2ndDerivative.x + f2ndDerivative.y, 3.0 ) ) );

    vecCurvature[i] = curvature2D;

    posOlder = posOld;
    posOld = pos;

It works on non-closed pointlists as well. For closed contours, you may would like to change the boundary behavior (for the first iterations).


Explanation for the derivatives:

A derivative for a continuous 1 dimensional function f(t) is:

But we are in a discrete space and have two discrete functions f_x(t) and f_y(t) where the smallest step for t is one.

The second derivative is the derivative of the first derivative:

Using the approximation of the first derivative, it yields to:

There are other approximations for the derivatives, if you google it, you will find a lot.