Ask Your Question
1

Last convexity defect not working

asked 2017-02-01 14:16:01 -0600

mddrill gravatar image

I am trying to write code to track hands. I am using the convexity defects function to find fingers, but for some reason, there seems to always be a problem with the last defect.

Here is a picture of what I'm talking about: pasteboard.co/tcOYWEp69.png (sorry, i''m new to the forum, so cannot post images, but there is no way for me to ask this question without posting one. It's also impossible for me to build karma, because the questions on here are way too advanced for me to answer, so please bear with me, thank you)

The cyan line is the contours, the yellow line is the hull points, and the red lines are the defect points. As you can see the last defect point detects the defect from the wrong side of the contour.

Here is my code:

#include "opencv2\opencv.hpp"

using namespace cv;
using namespace std;

int main() {
    VideoCapture cap(0);
    Mat src, gray, background, binary, diff;
    cap >> background;
    cvtColor(background, background, CV_BGR2GRAY);
    vector<vector<Point>> contours;
    vector < vector<int>> hullI = vector<vector<int>>(1);
    vector < vector<Point>> hullP = vector<vector<Point>>(1);
    vector<Vec4i> defects;
    while (waitKey(30)!='q') {
        cap >> src;
        cvtColor(src, gray, CV_BGR2GRAY);
        blur(gray, gray, Size(3, 3));
        absdiff(gray, background, diff);
        threshold(diff, binary, 15, 255, THRESH_BINARY);
        erode(binary, binary, Mat(Size(5, 5), CV_8U));

        imshow("binary", binary);

        findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        if (!contours.empty()) {
            sort(contours.begin(), contours.end(), [](vector<Point> a, vector<Point> b) { return a.size() > b.size(); });
            drawContours(src, contours, 0, Scalar(255, 255, 0));

            convexHull(contours[0], hullI[0]);
            convexHull(contours[0], hullP[0]);
            drawContours(src, hullP, 0, Scalar(0, 255, 255));

            if (hullI[0].size() > 2) {
                convexityDefects(contours[0], hullI[0], defects);

                for (Vec4i defect : defects) {
                    line(src, contours[0][defect[0]], contours[0][defect[2]], Scalar(0, 0, 255));
                    line(src, contours[0][defect[1]], contours[0][defect[2]], Scalar(0, 0, 255));
                }
            }
        }
        imshow("src", src);
        char key = waitKey(30);
        if (key == 'q')break;
        else if (key == 'p') waitKey();
        else if (key == 'b') {
            cap >> background;
            cvtColor(background, background, CV_BGR2GRAY);
        }
    }
}

I have confirmed through experiments that it is always the last defect in the defect vector that this happens too. Is this a bug in opencv or am I doing something wrong?

edit retag flag offensive close merge delete

Comments

Please give opencv version and platform

LBerger gravatar imageLBerger ( 2017-02-01 14:18:19 -0600 )edit
2

answered on stackoverflow

sturkmen gravatar imagesturkmen ( 2017-02-01 18:36:57 -0600 )edit

@sturkmen, care to repeat your answer here ?

berak gravatar imageberak ( 2017-02-02 02:49:54 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2017-02-02 06:34:45 -0600

i tested your code (with a small modification) with the image below (OpenCV version is 3.2).

as you can see on the result image it works as expected. probably you are using an old version of OpenCV and getting a buggy result. (i think it was a bug recently fixed)

image description

image description

#include "opencv2\opencv.hpp"

using namespace cv;
using namespace std;

int main() {
    //VideoCapture cap(0);
    Mat src, gray, background, binary, diff;
    //cap >> background;
    //cvtColor(background, background, CV_BGR2GRAY);
    vector<vector<Point> > contours;
    vector < vector<int> > hullI = vector<vector<int> >(1);
    vector < vector<Point> > hullP = vector<vector<Point> >(1);
    vector<Vec4i> defects;
        src = imread("hand.png");
        cvtColor(src, gray, CV_BGR2GRAY);
        blur(gray, gray, Size(3, 3));
        threshold(gray, binary, 150, 255, THRESH_BINARY_INV);
        //erode(binary, binary, Mat(Size(5, 5), CV_8U));
        imshow("binary", binary);
        findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        if (!contours.empty()) {
            sort(contours.begin(), contours.end(), [](vector<Point> a, vector<Point> b) { return a.size() > b.size(); });
            drawContours(src, contours, 0, Scalar(255, 255, 0));

            convexHull(contours[0], hullI[0]);
            convexHull(contours[0], hullP[0]);
            drawContours(src, hullP, 0, Scalar(0, 255, 255));

            if (hullI[0].size() > 2) {
                convexityDefects(contours[0], hullI[0], defects);

                for (Vec4i defect : defects) {
                    line(src, contours[0][defect[0]], contours[0][defect[2]], Scalar(0, 0, 255));
                    line(src, contours[0][defect[1]], contours[0][defect[2]], Scalar(0, 0, 255));
                }
            }
        }
        imshow("result", src);
        char key = waitKey(0);
        return 0;
    }
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-02-01 14:16:01 -0600

Seen: 489 times

Last updated: Feb 02 '17