Convexity defects C++ OpenCv

前端 未结 2 638
小蘑菇
小蘑菇 2020-12-01 10:07

I would be grateful to you if you could help me with this issue :)

Relating to this question cvConvexityDefects in OpenCV 2.X / C++?, I have the same problem. The Op

相关标签:
2条回答
  • 2020-12-01 10:18

    I raised this question because I wasn't able to figure out a solution (it is not only today that I was dealing with the matter hehe), but after all I was able to manage the problem!

    I had to change the way I calculated the convex hull, using the index array form. So now we have a vector< int > instead a vector< Point >.

    This is the code I used (it works I painted the points over an image):

    void HandDetection::findConvexityDefects(vector<Point>& contour, vector<int>& hull, vector<Point>& convexDefects){
        if(hull.size() > 0 && contour.size() > 0){
        CvSeq* contourPoints;
        CvSeq* defects;
        CvMemStorage* storage;
        CvMemStorage* strDefects;
        CvMemStorage* contourStr;
        CvConvexityDefect *defectArray = 0;
    
        strDefects = cvCreateMemStorage();
        defects = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq),sizeof(CvPoint), strDefects );
    
        //We transform our vector<Point> into a CvSeq* object of CvPoint.
        contourStr = cvCreateMemStorage();
        contourPoints = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), contourStr);
        for(int i=0; i<(int)contour.size(); i++) {
            CvPoint cp = {contour[i].x,  contour[i].y};
            cvSeqPush(contourPoints, &cp);
        }
    
        //Now, we do the same thing with the hull index
        int count = (int)hull.size();
        //int hullK[count];
        int* hullK = (int*)malloc(count*sizeof(int));
        for(int i=0; i<count; i++){hullK[i] = hull.at(i);}
        CvMat hullMat = cvMat(1, count, CV_32SC1, hullK);
    
        //We calculate convexity defects
        storage = cvCreateMemStorage(0);
        defects = cvConvexityDefects(contourPoints, &hullMat, storage);
        defectArray = (CvConvexityDefect*)malloc(sizeof(CvConvexityDefect)*defects->total);
        cvCvtSeqToArray(defects, defectArray, CV_WHOLE_SEQ);
        //printf("DefectArray %i %i\n",defectArray->end->x, defectArray->end->y);
    
        //We store defects points in the convexDefects parameter.
        for(int i = 0; i<defects->total; i++){
            CvPoint ptf;
            ptf.x = defectArray[i].depth_point->x;
            ptf.y = defectArray[i].depth_point->y;
            convexDefects.push_back(ptf);
        }
    
        //We release memory
        cvReleaseMemStorage(contourStr);
        cvReleaseMemStorage(strDefects);
        cvReleaseMemStorage(storage);
        }
    }
    

    This worked for me. If you see something wrong or another way to manage it, please tell me!

    0 讨论(0)
  • 2020-12-01 10:38

    found some direct approach using the cpp convexityDefects. Typehandling by convexHull-function. It fills by type, int* returns indizes, Point* returns coordinates.

    void WorkFrame( Mat img, double minArea )
    {
    //assumption:
    // img already preprocessed, threshold, gray, smooth, morphology whatever..
    
    //get some contours
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours( img, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
    
    for( int i=0; i<contours.size(); i++ ) 
    {
        vector<Point>& c=contours[i];
        double area = contourArea( c );
            if( area<minArea ){ continue; } //filter remaining noise
    
        //convexHull works typedependent.
        //std::vector<Point> ptHull1; //uncomment and compare to ptHull2
        //convexHull( c, ptHull1 ); //convexHull is smart and fills direct coordinates
    
        std::vector<int> ihull; 
        convexHull( c, ihull ); //convexHull is smart and fills in contourIndices
    
        std::vector<Vec4i> defects;
        convexityDefects( c, ihull, defects ); //expects indexed hull (internal assertion mat.channels()==1)
    
        std::vector< Point > ptHull2;
        std::vector<int>::iterator ii=ihull.begin();
        while( ii!=ihull.end() )
        {
            int idx=(*ii);
            ptHull2.push_back( c[idx] );
            ii++;
        }
        cv::polylines( mat, c, true, Scalar( 0xCC,0xCC,0xCC ), 1 );
        cv::polylines( mat, ptHull2, true, Scalar( 0xFF, 0x20, 0x20 ), 1 );
    
        std::vector<Vec4i>::iterator d=defects.begin();
        while( d!=defects.end() )
        {
            Vec4i& v=(*d); d++;
            int startidx=v[0]; Point ptStart( c[startidx] );
            int endidx=v[1]; Point ptEnd( c[endidx] );
            int faridx=v[2]; Point ptFar( c[faridx] );
    
            cv::circle( img, ptStart, 4, Scalar( 0x02,0x60,0xFF ), 2 );
            cv::circle( img, ptEnd,   4, Scalar( 0xFF,0x60,0x02 ), 2 );
            cv::circle( img, ptFar,   4, Scalar( 0x60,0xFF,0x02 ), 2 );
        }
    }
    

    }

    0 讨论(0)
提交回复
热议问题