Ask Your Question

Revision history [back]

i've answered a smilar question before.

i trial code based on convexityDefects gives you some key points.maybe you will improve it.

result images :

image description image description

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( argv[1] );
    if (src.empty())
        return -1;

    Mat bw;
    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 60;

    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contourArea(contours[i]) > 500 )
        {
            approxPolyDP(contours[i],contours[i],9,true);
            convexHull(contours[i], contoursHull,true);
            convexityDefects(contours[i], contoursHull,defects);

            for ( size_t j = 0; j <  defects.size(); j++)
            {
                Vec4i defpoint = defects[j];
                circle(src,contours[i][defpoint[2]],2,Scalar(0,255,0),1);
            }
        }
    }
    imshow("result", src);
    waitKey();
    return 0;
}

i've answered a smilar question before.

i trial code based on convexityDefects gives you some key points.maybe you will improve it.it or i will try to improve when i find time.

(also see smilar question i've answered with almost same code before.)

result images :

image description image description

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( argv[1] );
    if (src.empty())
        return -1;

    Mat bw;
    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 60;

    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contourArea(contours[i]) > 500 )
        {
            approxPolyDP(contours[i],contours[i],9,true);
            convexHull(contours[i], contoursHull,true);
            convexityDefects(contours[i], contoursHull,defects);

            for ( size_t j = 0; j <  defects.size(); j++)
            {
                Vec4i defpoint = defects[j];
                circle(src,contours[i][defpoint[2]],2,Scalar(0,255,0),1);
            }
        }
    }
    imshow("result", src);
    waitKey();
    return 0;
}

a trial code based on convexityDefects gives you some key points.maybe you will improve it or i will try to improve when i find time.

(also see smilar question i've answered with almost same code before.)

result images :

image description image description

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( argv[1] );
    if (src.empty())
        return -1;

    Mat bw;
    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 60;

    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contourArea(contours[i]) > 500 )
        {
            approxPolyDP(contours[i],contours[i],9,true);
            convexHull(contours[i], contoursHull,true);
            convexityDefects(contours[i], contoursHull,defects);

            for ( size_t j = 0; j <  defects.size(); j++)
            {
                Vec4i defpoint = defects[j];
                circle(src,contours[i][defpoint[2]],2,Scalar(0,255,0),1);
            }
        }
    }
    imshow("result", src);
    waitKey();
    return 0;
}

EDIT 1: i tried to improve my solution by checking nonzero pixels count around the defect point.

result is perfect for the test images.

image description image description

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( argv[1] );
    if (src.empty())
        return -1;

    Mat bw;
    cvtColor( src, bw, COLOR_BGR2GRAY );

    bw = bw < 60;

    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours( bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contourArea(contours[i]) > 500 )
        {
            approxPolyDP(contours[i],contours[i],2,true);
            convexHull(contours[i], contoursHull,true);
            convexityDefects(contours[i], contoursHull,defects);

            for ( size_t j = 0; j <  defects.size(); j++)
            {
                Vec4i defpoint = defects[j];
                Point pt = contours[i][defpoint[2]]; // get defect point
                Rect r3x3(pt.x-2, pt.y-2, 5, 5 ); // create 5x5 Rect from defect point

                // maybe no need but to be sure that the rect is in the image
                r3x3 = r3x3 & Rect(0, 0, bw.cols, bw.rows );

                int non_zero_pixels = countNonZero( bw(r3x3) );
                cout << non_zero_pixels << endl;
                if( non_zero_pixels > 17 )
                    circle(src,contours[i][defpoint[2]],2,Scalar(0,255,0),1);
            }
        }
    }
    imshow("result", src);
    waitKey();
    return 0;
}

a trial code based on convexityDefects gives you some key points.maybe you will improve it or i will try to improve when i find time.

(also see smilar question i've answered with almost same code before.)

result images :

image description image description

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( argv[1] );
    if (src.empty())
        return -1;

    Mat bw;
    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 60;

    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE RETR_EXTERNAL, CHAIN_APPROX_NONE );

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contourArea(contours[i]) > 500 )
        {
            approxPolyDP(contours[i],contours[i],9,true);
            convexHull(contours[i], contoursHull,true);
            convexityDefects(contours[i], contoursHull,defects);

            for ( size_t j = 0; j <  defects.size(); j++)
            {
                Vec4i defpoint = defects[j];
                circle(src,contours[i][defpoint[2]],2,Scalar(0,255,0),1);
            }
        }
    }
    imshow("result", src);
    waitKey();
    return 0;
}

EDIT 1: i tried to improve my solution by checking nonzero pixels count around the defect point.

result is perfect for the test images.

image description image description

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( argv[1] );
    if (src.empty())
        return -1;

    Mat bw;
    cvtColor( src, bw, COLOR_BGR2GRAY );

    bw = bw < 60;

    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours( bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE RETR_EXTERNAL, CHAIN_APPROX_NONE );

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contourArea(contours[i]) > 500 )
        {
            approxPolyDP(contours[i],contours[i],2,true);
            convexHull(contours[i], contoursHull,true);
            convexityDefects(contours[i], contoursHull,defects);

            for ( size_t j = 0; j <  defects.size(); j++)
            {
                Vec4i defpoint = defects[j];
                Point pt = contours[i][defpoint[2]]; // get defect point
                Rect r3x3(pt.x-2, pt.y-2, 5, 5 ); // create 5x5 Rect from defect point

                // maybe no need but to be sure that the rect is in the image
                r3x3 = r3x3 & Rect(0, 0, bw.cols, bw.rows );

                int non_zero_pixels = countNonZero( bw(r3x3) );
                cout << non_zero_pixels << endl;
                if( non_zero_pixels > 17 )
                    circle(src,contours[i][defpoint[2]],2,Scalar(0,255,0),1);
            }
        }
    }
    imshow("result", src);
    waitKey();
    return 0;
}