Ask Your Question

Revision history [back]

My first answer was wrong. @Matman answer is good but I think problem is in blurred image.

If you don't blur enough image you will have many double points. You shape become a line but at beginning your shape could be a rectangle.

if you find double point in your contour may be you have to increase blurring (shape like 8 could be a problem). For fractal shape (or with a large rugosity) it is difficult to delete those points.

In this example I use : surface rectangle 6 (width 3 and height 2)

canny witout blurring Image 0

canny with blur size 3 image 1

Canny with blur size 5 image 2

image description

Source file

{
    Mat x = Mat::zeros(20,20,CV_8UC1);
    Mat result = Mat::zeros(20,20,CV_8UC3);
    vector<Vec3b> c = { Vec3b(255, 0, 0), Vec3b(0,255,0),Vec3b(0,0,255),Vec3b(255, 255, 0),Vec3b(255, 0, 255),Vec3b(0, 255, 255) };
    for (int i=9;i<=10;i++)
        for (int j = 9; j <= 11; j++)
        {
        x.at<uchar>(i,j)=255;
        result.at<Vec3b>(i,j)=Vec3b(255,255,255);
        }
    imwrite("square.png",x);
    Mat idx;
    findNonZero(x,idx);
    cout << "Square surface " << idx.rows<<endl;
    vector<vector<vector<Point> >> contours(3);
    vector<Vec4i> hierarchy;
    double thresh=1;
    int aperture_size=3;
    vector<Mat> xx(3);
    vector<Mat> dst(3);
    for (size_t i = 0; i < xx.size(); i++)
    {
        if (i==0)
            xx[i]=x.clone();
        else
            blur(x, xx[i], Size(static_cast<int>(2*i+1),static_cast<int>(2*i+1)));
        Canny(xx[i], dst[i],thresh, thresh, 3,true );
        namedWindow(format("canny%d",i),WINDOW_NORMAL);
        namedWindow(format("result%d",i),WINDOW_NORMAL);
        imshow(format("canny%d",i),dst[i]);
        findContours(dst[i],contours[i], hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
   }

    namedWindow("original image",WINDOW_NORMAL);
    imshow("original image",x);
   /*     
    Mat dx,dy,g;
    Sobel(x, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
    Sobel(x, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
    namedWindow("gradient modulus",WINDOW_NORMAL);
    g = dx.mul(dx) + dy.mul(dy);
    imshow("gradient modulus",g);
    findContours(x,contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
    cout << "#contours : " << contours.size()<<endl;
    if (contours.size() > 0)
    {
        for (size_t i = 0; i < contours.size(); i++)
        {
            cout << "#pixel in contour of original image :"<<contours[i].size()<<endl;
            for (size_t j=0;j<contours[i].size();j++)
                cout << contours[i][j] << "*";
            cout<<endl;
            drawContours(result, contours, i, c[i]);
        }
    }*/

    size_t maxContour=0;
    for (size_t k = 0; k < 3; k++)
    {
        cout << "#contours("<<k<<") : " << contours[k].size()<<endl;;
        if (maxContour<contours[k].size())
            maxContour= contours[k].size();
        if (contours[k].size() > 0)
        {
            for (size_t i = 0; i<contours[k].size();i++)
            {
                cout << "#pixel in contour using canny with original image :"<<contours[i].size()<<endl;
                for (size_t j=0;j<contours[k][i].size();j++)
                    cout << contours[k][i][j] << "*";
                cout<<endl;
            }

        }
        else
            cout << "No contour found "<<endl;

    }
    int index=0;
    while (true)
    {
        char key = (char)waitKey();
        if( key == 27 )
            break;

        if (key == '+')
        {
            index = (index+1)%maxContour;
        }
        if (key == '-')
        {
            index = (index-1);
            if (index<0)
                index = maxContour-1;
        }
        vector<Mat> result(contours.size());
        for (size_t k = 0; k < contours.size(); k++)
        {
           result[k] = Mat::zeros(20,20,CV_8UC3);
           for (int ii=9;ii<=10;ii++)
                for (int jj = 9; jj <= 11; jj++)
                {
                    result[k].at<Vec3b>(ii,jj)=Vec3b(255,255,255);
                }

            if (index<contours[k].size())
                drawContours(result[k], contours[k], static_cast<int>(index), c[index]);
            else
                cout << "No Contour "<<index<<" in image "<<k<<endl;
            imshow(format("result%d",k),result[k]);
        }
        cout << "Contour "<<index<<endl;
    }
    exit(0);
}