Ask Your Question
2

Convexity Defects in OpenCV 2.4.2

asked 2012-09-20 10:59:48 -0500

imran gravatar image

updated 2012-10-01 09:09:38 -0500

Can anyone tell me if convexityDefects() is supported in OpenCV 2.4.2. The documentation says it does but I'm getting an error when trying to use it and I can't seem to find the problem. The error I get is,

convexDefect.cpp: In function ‘cv::Mat contour(cv::Mat)’:
convexDefect.cpp:68:66: error: no match for call to ‘(std::vector<cv::Point_<int> >)
(std::vector<cv::Point_<int> >&, std::vector<cv::Point_<int> >&, 
std::vector<cv::Point_<int> >&)

Can somebody perhaps identify the problem? Below is my code (The code reads in an image, finds the contours, the convex hull and supposed to find the convexity defects).

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <fstream>
using std::ifstream;
using std::ofstream;
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;
#include <dirent.h>
#include <cstdlib> 
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string>
using namespace std;
using namespace cv;

Mat contour(Mat image);

int main( int argc, const char** argv )
{
    Mat image = imread( argv[1], 1 );       
    Mat new_image = contour(image);
    imshow("Output", new_image);
    waitKey();      
    return 0;
}

Mat contour(Mat image)
{
    cvtColor(image,image,CV_BGR2GRAY);

    int threshval = 40;
    int max_thresh = 255;
    RNG rng(12345);

    Mat threshold_output;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    threshold( image, threshold_output, threshval, 255, THRESH_BINARY );

    findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    Mat cimage = Mat::zeros(image.size(), CV_8UC3);

    for(size_t i = 0; i < contours.size(); i++)
    {
        size_t count = contours[i].size();
        if( count < 6 )
            continue;

        Mat pointsf;
        Mat(contours[i]).convertTo(pointsf, CV_32F);
        RotatedRect box = fitEllipse(pointsf);
        if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*30 )
            continue;
        drawContours(cimage, contours, (int)i, Scalar::all(255), 1, 8, vector<Vec4i>(), 0, Point());

         //Convex Hull -------------
         // vector<Point> hullPoints;   
         vector<int> hullIndices; 
         vector<Vec4i> convexityDefects;

        //convexHull(contours[i], hullPoints, true, true);
        convexHull(contours[i], hullIndices, true);
        convexityDefects(contours[i], hullIndices, convexityDefects);

    //int hullcount = (int)hullPoints.size();
        /*for( int j = 1; j < hullcount; j++ )
        {
            line(cimage, hullPoints[j-1], hullPoints[j], Scalar(0, 255, 0), 1, CV_AA);
            circle(cimage,  hullPoints[j], 1, Scalar(0, 0, 255), CV_FILLED, CV_AA);
        }*/
    }
    return cimage;
}
edit retag flag offensive close merge delete

3 answers

Sort by » oldest newest most voted
2

answered 2012-09-29 07:51:23 -0500

Rob gravatar image

This solves your problem:

// 1) Your contour needs to be of type std::vector<cv::point>

std::vector<cv::Point> contour;

// 2) If you've got contour using findcontours, you've got a std::vector<std::vector<cv::point>> contour_set; that you can pass like this: contour_set[i] instead of contour in the convexHull-method (see below)

// 3) Determine the convex Hull based on int-indeces for contour point localization // ATTENTION: <int> gives you the 'contour element indeces' (= convex hull's key points)!!!!

cv::vector<int> convexHull_IntIdx;          
cv::convexHull(contour, convexHull_IntIdx, true);

// 4) Use the convexityDefects method to determine the convexity defects

std::vector<cv::Vec4i> convexityDefectsSet;     // Here will be start, end point and "most deep" point (the convexity defect, see the documentation-picture) as well as its distance (depth) to the start-end-line determined... as a vector: for each convexity defect one vector-element
cv::convexityDefects(contour, convexHull_IntIdx, convexityDefectsSet);

// 5) You can then access the 4 parameters that this function calculates (start, end, depth/defect-point and depth) like this:

for (int cDefIt = 0; cDefIt < convexityDefectsSet.size(); cDefIt++)
{
int startIdx = convexityDefectsSet[cDefIt].val[0];
int endIdx = convexityDefectsSet[cDefIt].val[1];
int defectPtIdx = convexityDefectsSet[cDefIt].val[2];
double depth = (double)convexityDefectsSet[cDefIt].val[3]/256.0f;  // see documentation link below why this

// do something with *contour[defectPtIdx]*.. This is e.g. the defect point.

}

See for more infos the documentation: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#void convexityDefects(InputArray contour, InputArray convexhull, OutputArray convexityDefects)

edit flag offensive delete link more

Comments

@Rob I have made the changes you suggested. Thank you. I, however, still have the same error coming up. Here is the error,

convexDefect.cpp: In function ‘cv::Mat contour(cv::Mat)’: convexDefect.cpp:68:68: error: no match for call to ‘(std::vector<cv::Vec<int, 4> >) (std::vector<cv::Point_<int> >&, std::vector<int>&, std::vector<cv::Vec<int, 4> >&)’

I edited the code in the question above to reflect the changes I have made, is this correct? If possible, can you check if it works on your machine?

imran gravatar imageimran ( 2012-10-01 09:13:05 -0500 )edit

Do you know how to get the startIdx or defectPtIdx from the convexityDefects function in OpenCV4Android library?

Dali gravatar imageDali ( 2013-01-02 18:27:58 -0500 )edit
1

answered 2012-09-29 06:32:53 -0500

wajihullahbaig gravatar image

updated 2012-09-29 06:54:11 -0500

Check out this answer

convexity defects C++ OpenCv

HullPoints should not be a vector of points. Instead a vector of int. But for a working examples Check out the sample in the documentation below

http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/hull/hull.html

edit flag offensive delete link more

Comments

@wajihullahbaig Thank you for the suggestions. I have changed the vector of points to a vector of int but I still get the same error. I changed the code in the question above to reflect the changes that I have made. I checked the links you suggested. The first link was a solution using C and I'm hoping to solve it in C++. The second link is an example of hull method without the use of convexity defects.

imran gravatar imageimran ( 2012-10-01 09:14:46 -0500 )edit

I need to find number of convex deficient region in image..following error is coming error: no match for call to ‘(std::vector<std::vector<cv::vec<int, 4=""> > >) (std::vector<cv::point_<int> >&, std::vector<int>&, std::vector<std::vector<cv::vec<int, 4=""> > >&)’ convexityDefects(contours[i], hullIndices, convexityDefects);

Please suggest how to resolve this error.

vidushig2 gravatar imagevidushig2 ( 2017-03-18 09:38:57 -0500 )edit
0

answered 2013-04-03 17:02:18 -0500

iVlad gravatar image

updated 2013-04-03 17:03:46 -0500

ConvexityDefects() might not work well in 5-10% of cases, see conv_defect.jpg; as shown in the picture a left image is when a convexity defect was successfully extracted (little red dot between fingers) and the right one is when the function failed. I am looking into the code to report why.

edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2012-09-20 10:59:48 -0500

Seen: 9,793 times

Last updated: Apr 03 '13