Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

About contours of the blob,area of blob's hole and contours hierarchy

Hi all, this is test image.

image description

I have some qestion here:

1.in opencv doucument:"hierarchy – Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative." The hiearchy which i define in code is right or not? If it's wrong, how to correct??

2.I check of orginal the area of the blob's hole should be equal the area of invert the orginal image in some place. But in fact, in this code , i can not find they are the same.

I hope someone could tell me in detail. Appreciate you!

And Code List here:

#define BLOB_NO_HOLE(hierarchy) ( (((hierarchy[2]==-1) && (hierarchy[3]==-1))?1:0) )
#define IS_TOPLEVEL(hierarchy) ( (((hierarchy[2]!=-1) && (hierarchy[3]==-1))?1:0) )
#define IS_CC(hierarchy) ( (hierarchy[3]==-1?0:1) )
#define ONLY_HOLE(hierarchy) ( (((hierarchy[0]==-1)  &&(hierarchy[1]==-1) && (hierarchy[2]==-1))?1:0) )

Mat HolesAreaTest( Mat _src)
    {
        CV_Assert(_src.type()==CV_8UC1);
        Mat dst;
        vector<vector<cv::Point>> contours;
        vector<Vec4i> hierarchy;
        Mat r[10];

        findContours(_src.clone(), contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

        CvScalar color=cvScalar(255);
        dst=Mat::zeros(_src.size(),CV_8UC1);

        char* slen;
        char c[10];
        int idx = 0;

        cout <<" ===================A0======================= "<<endl;
        for( size_t i = 0; i< contours.size(); i++ )
        {   
            r[i]=Mat::zeros(_src.size(),CV_8UC1);

            drawContours(r[i], contours, (int)i, color, 0, 8, hierarchy, 0);

            cout << " Contour " << i << ":" << endl;
            cout << " next contour: " << hierarchy[i][0] << endl;
            cout << " previous contour: " << hierarchy[i][1] << endl;
            cout << " child contour: " << hierarchy[i][2] << endl;
            cout << " parent contour: " << hierarchy[i][3] << endl;
            cout << " size: " << contours[i].size() << endl;
            cout << " BLOB NO HOLE: " << BLOB_NO_HOLE(hierarchy[i]) << endl;
            cout << " HOLE:" << ONLY_HOLE(hierarchy[i])<<endl;
            cout << " Top-level: " << IS_TOPLEVEL(hierarchy[i]) << endl;
            cout << " CC: " << IS_CC(hierarchy[i]) << endl;
            sprintf(c,"%d",i);

            char* slen= strcat(c,"A1");
            imshow(slen,r[(int)i]);
            r[i]=Mat::zeros(_src.size(),CV_8UC1);
        }

        cout <<" ===================A1======================= "<<endl;
        for( int idx = 0; idx < contours.size(); idx++ )
        {
            if ONLY_HOLE(hierarchy[idx]) 
            {
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx])-cv::arcLength(contours[idx],true);
                cout<<" index:"<<idx<<endl;
                cout << " Hole size:" <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A2");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ==================A2======================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            r[idx]=Mat::zeros(_src.size(),CV_8UC1);
            c[idx]=NULL;
            if BLOB_NO_HOLE(hierarchy[idx]) 
            {
                cout << "Drawing BLOB NO HOLE index:" << idx <<endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "Hole size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A3");
                imshow(slen,r[(int)idx]);
            }

        }

        cout <<" ===================A3======================= "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_TOPLEVEL(hierarchy[idx]) {
                cout << "Drawing top-level node (" << idx << ")" << endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A4");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ====================A4====================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_CC(hierarchy[idx])
            {
                //compCount++;
                cv::Scalar color(rand()&255, rand()&255, rand()&255);
                cout << "Drawing " << idx << " with color " << cv::Mat(color) << endl;
                drawContours(r[idx], contours, idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A5");
                imshow(slen,r[(int)idx]);
            }
        }
        cout <<" ====================invert====================== "<<endl;

         Mat invertMat;
         subtract(255,_src,invertMat);

        findContours(invertMat, contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

         cout <<" ===================B0======================= "<<endl;
        for( size_t i = 0; i< contours.size(); i++ )
        {   
            r[i]=Mat::zeros(_src.size(),CV_8UC1);

            drawContours(r[i], contours, (int)i, color, 0, 8, hierarchy, 0);

            cout << " Contour " << i << ":" << endl;
            cout << " next contour: " << hierarchy[i][0] << endl;
            cout << " previous contour: " << hierarchy[i][1] << endl;
            cout << " child contour: " << hierarchy[i][2] << endl;
            cout << " parent contour: " << hierarchy[i][3] << endl;
            cout << " size: " << contours[i].size() << endl;
            cout << " BLOB NO HOLE: " << BLOB_NO_HOLE(hierarchy[i]) << endl;
            cout << " HOLE:" << ONLY_HOLE(hierarchy[i])<<endl;
            cout << " Top-level: " << IS_TOPLEVEL(hierarchy[i]) << endl;
            cout << " CC: " << IS_CC(hierarchy[i]) << endl;
            sprintf(c,"%d",i);

            char* slen= strcat(c,"B0");
            imshow(slen,r[(int)i]);
            r[i]=Mat::zeros(_src.size(),CV_8UC1);
        }

        cout <<" ===================B1======================= "<<endl;

        for( int idx = 0; idx < contours.size(); idx++ )
        {
            if ONLY_HOLE(hierarchy[idx]) 
            {
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx])-cv::arcLength(contours[idx],true);
                cout<<" index:"<<idx<<endl;
                cout << " Hole size:" <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"B1");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ==================B2======================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            r[idx]=Mat::zeros(_src.size(),CV_8UC1);
            c[idx]=NULL;
            if BLOB_NO_HOLE(hierarchy[idx]) 
            {
                cout << "Drawing BLOB NO HOLE index:" << idx <<endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "Hole size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"B2");
                imshow(slen,r[(int)idx]);
            }

        }

        cout <<" ===================B3======================= "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_TOPLEVEL(hierarchy[idx]) {
                cout << "Drawing top-level node (" << idx << ")" << endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"B3");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ====================B4====================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_CC(hierarchy[idx])
            {
                //compCount++;
                cv::Scalar color(rand()&255, rand()&255, rand()&255);
                cout << "Drawing " << idx << " with color " << cv::Mat(color) << endl;
                drawContours(r[idx], contours, idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"r4");
                imshow(slen,r[(int)idx]);
            }
        }

        dst=_src;
        imshow("dst",dst);

        return dst;
    }

About contours of the blob,area of blob's hole and contours hierarchy

Hi all, this is test image.

image description

I have some qestion here:

1.in opencv doucument:"hierarchy – Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative." The hiearchy which i define in code is right or not? If it's wrong, how to correct??

2.I check of orginal the area of the blob's hole should be equal the area of invert the orginal image in some place. But in fact, in this code , i can not find they are the same.

I hope someone could tell me in detail. Appreciate you!

And Code List here:

#define BLOB_NO_HOLE(hierarchy) ( (((hierarchy[2]==-1) && (hierarchy[3]==-1))?1:0) )
#define IS_TOPLEVEL(hierarchy) ( (((hierarchy[2]!=-1) && (hierarchy[3]==-1))?1:0) )
#define IS_CC(hierarchy) ( (hierarchy[3]==-1?0:1) )
#define ONLY_HOLE(hierarchy) ( (((hierarchy[0]==-1)  &&(hierarchy[1]==-1) && (hierarchy[2]==-1))?1:0) )

Mat HolesAreaTest( Mat _src)
    {
        CV_Assert(_src.type()==CV_8UC1);
        Mat dst;
        vector<vector<cv::Point>> contours;
        vector<Vec4i> hierarchy;
        Mat r[10];

        findContours(_src.clone(), contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

        CvScalar color=cvScalar(255);
        dst=Mat::zeros(_src.size(),CV_8UC1);

        char* slen;
        char c[10];
        int idx = 0;

        cout <<" ===================A0======================= "<<endl;
        for( size_t i = 0; i< contours.size(); i++ )
        {   
            r[i]=Mat::zeros(_src.size(),CV_8UC1);

            drawContours(r[i], contours, (int)i, color, 0, 8, hierarchy, 0);

            cout << " Contour " << i << ":" << endl;
            cout << " next contour: " << hierarchy[i][0] << endl;
            cout << " previous contour: " << hierarchy[i][1] << endl;
            cout << " child contour: " << hierarchy[i][2] << endl;
            cout << " parent contour: " << hierarchy[i][3] << endl;
            cout << " size: " << contours[i].size() << endl;
            cout << " BLOB NO HOLE: " << BLOB_NO_HOLE(hierarchy[i]) << endl;
            cout << " HOLE:" << ONLY_HOLE(hierarchy[i])<<endl;
            cout << " Top-level: " << IS_TOPLEVEL(hierarchy[i]) << endl;
            cout << " CC: " << IS_CC(hierarchy[i]) << endl;
            sprintf(c,"%d",i);

            char* slen= strcat(c,"A1");
            imshow(slen,r[(int)i]);
            r[i]=Mat::zeros(_src.size(),CV_8UC1);
        }

        cout <<" ===================A1======================= "<<endl;
        for( int idx = 0; idx < contours.size(); idx++ )
        {
            if ONLY_HOLE(hierarchy[idx]) 
            {
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx])-cv::arcLength(contours[idx],true);
a=cv::contourArea(contours[idx]);
                cout<<" index:"<<idx<<endl;
                cout << " Hole size:" <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A2");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ==================A2======================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            r[idx]=Mat::zeros(_src.size(),CV_8UC1);
            c[idx]=NULL;
            if BLOB_NO_HOLE(hierarchy[idx]) 
            {
                cout << "Drawing BLOB NO HOLE index:" << idx <<endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "Hole size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A3");
                imshow(slen,r[(int)idx]);
            }

        }

        cout <<" ===================A3======================= "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_TOPLEVEL(hierarchy[idx]) {
                cout << "Drawing top-level node (" << idx << ")" << endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A4");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ====================A4====================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_CC(hierarchy[idx])
            {
                //compCount++;
                cv::Scalar color(rand()&255, rand()&255, rand()&255);
                cout << "Drawing " << idx << " with color " << cv::Mat(color) << endl;
                drawContours(r[idx], contours, idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"A5");
                imshow(slen,r[(int)idx]);
            }
        }
        cout <<" ====================invert====================== "<<endl;

         Mat invertMat;
         subtract(255,_src,invertMat);

        findContours(invertMat, contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

         cout <<" ===================B0======================= "<<endl;
        for( size_t i = 0; i< contours.size(); i++ )
        {   
            r[i]=Mat::zeros(_src.size(),CV_8UC1);

            drawContours(r[i], contours, (int)i, color, 0, 8, hierarchy, 0);

            cout << " Contour " << i << ":" << endl;
            cout << " next contour: " << hierarchy[i][0] << endl;
            cout << " previous contour: " << hierarchy[i][1] << endl;
            cout << " child contour: " << hierarchy[i][2] << endl;
            cout << " parent contour: " << hierarchy[i][3] << endl;
            cout << " size: " << contours[i].size() << endl;
            cout << " BLOB NO HOLE: " << BLOB_NO_HOLE(hierarchy[i]) << endl;
            cout << " HOLE:" << ONLY_HOLE(hierarchy[i])<<endl;
            cout << " Top-level: " << IS_TOPLEVEL(hierarchy[i]) << endl;
            cout << " CC: " << IS_CC(hierarchy[i]) << endl;
            sprintf(c,"%d",i);

            char* slen= strcat(c,"B0");
            imshow(slen,r[(int)i]);
            r[i]=Mat::zeros(_src.size(),CV_8UC1);
        }

        cout <<" ===================B1======================= "<<endl;

        for( int idx = 0; idx < contours.size(); idx++ )
        {
            if ONLY_HOLE(hierarchy[idx]) 
            {
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx])-cv::arcLength(contours[idx],true);
a=cv::contourArea(contours[idx]);
                cout<<" index:"<<idx<<endl;
                cout << " Hole size:" <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"B1");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ==================B2======================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            r[idx]=Mat::zeros(_src.size(),CV_8UC1);
            c[idx]=NULL;
            if BLOB_NO_HOLE(hierarchy[idx]) 
            {
                cout << "Drawing BLOB NO HOLE index:" << idx <<endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "Hole size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"B2");
                imshow(slen,r[(int)idx]);
            }

        }

        cout <<" ===================B3======================= "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_TOPLEVEL(hierarchy[idx]) {
                cout << "Drawing top-level node (" << idx << ")" << endl;
                drawContours(r[idx], contours, (int)idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"B3");
                imshow(slen,r[(int)idx]);
            }
        }

        cout <<" ====================B4====================== "<<endl;
        for(int idx = 0; idx < contours.size(); idx++)
        {
            if IS_CC(hierarchy[idx])
            {
                //compCount++;
                cv::Scalar color(rand()&255, rand()&255, rand()&255);
                cout << "Drawing " << idx << " with color " << cv::Mat(color) << endl;
                drawContours(r[idx], contours, idx, color, CV_FILLED, 8, hierarchy, 0);
                double a=cv::contourArea(contours[idx]);
                cout << "blob size: " <<a<< endl;
                sprintf(c,"%d",idx);
                char* slen= strcat(c,"r4");
                imshow(slen,r[(int)idx]);
            }
        }

        dst=_src;
        imshow("dst",dst);

        return dst;
    }