c++opencv

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


I did use the findcontours() 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!


Solution

  • 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< float > 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).

    UPDATE:

    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.