Ask Your Question
0

Hand detection not working.

asked 2017-01-02 19:19:40 -0600

I'm using OpenCV3 with Visual Studio 2015 in C++. I cannot seem to get the program to detect my hand only. It creates a contour of my hand and the surrounding wall when I don't make it only display the largest area contour. However when I force it to find and display only the largest area contour, it completely ignores my hand. I've tried it in several background cases including a white wall with just my hand. My code is as follows:

#include "opencv2\opencv.hpp"

using namespace cv;

void on_trackbar(int, void*) {
    // Dummy function
}

int main(int argv, char** argc) {
    Mat frame;
    Mat grayFrame;
    Mat hsvFrame;
    Mat thesholdFrame;
    VideoCapture capture;

    //Trackbar variables (H,S,V)
    int H_MIN = 0;
    int H_MAX = 180;
    int S_MIN = 0;
    int S_MAX = 255;
    int V_MIN = 0;
    int V_MAX = 255;




    namedWindow("trackbar", 0);
    //create memory to store trackbar name on window
    char TrackbarName[50];
    sprintf(TrackbarName, "H_MIN");
    sprintf(TrackbarName, "H_MAX");
    sprintf(TrackbarName, "S_MIN");
    sprintf(TrackbarName, "S_MAX");
    sprintf(TrackbarName, "V_MIN");
    sprintf(TrackbarName, "V_MAX");


    createTrackbar("H_MIN", "trackbar", &H_MIN, H_MAX, on_trackbar);
    createTrackbar("H_MAX", "trackbar", &H_MAX, H_MAX, on_trackbar);
    createTrackbar("S_MIN", "trackbar", &S_MIN, S_MAX, on_trackbar);
    createTrackbar("S_MAX", "trackbar", &S_MAX, S_MAX, on_trackbar);
    createTrackbar("V_MIN", "trackbar", &V_MIN, V_MAX, on_trackbar);
    createTrackbar("V_MAX", "trackbar", &V_MAX, V_MAX, on_trackbar);



    capture.open(0);
    std::vector<std::vector<cv::Point> > contours;


    while (true){
        capture >> frame;
        waitKey(10);

        cvtColor(frame, hsvFrame, COLOR_BGR2HSV);
        //imshow("HSV", hsvFrame);

        inRange(hsvFrame, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), thesholdFrame);
        int dilation_size = 3;
        Mat element = getStructuringElement(MORPH_ELLIPSE, Size(2 * dilation_size + 1, 2 * dilation_size + 1), Point(dilation_size, dilation_size));
        //medianBlur(hsvFrame, hsvFrame, 5);
        //dilate(hsvFrame, hsvFrame, element);
        findContours(thesholdFrame, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

        int largest_contour_area = 0;
        int largest_contour_area_index = 1;
        for (int i = 0; i < contours.size(); i++) {

            double contour_area = contourArea(contours[i], false);

            if (contour_area > largest_contour_area) {
                largest_contour_area = contour_area;
                largest_contour_area_index = i;
            }

        }

        drawContours(frame, contours, largest_contour_area_index, (0, 255, 0), 1);
        //drawContours(frame, contours, -1, (0, 255, 0), 3);
        putText(frame, "NO DETECTION", Point(25, 40), 2, 1, CV_RGB(255, 255, 0), 1, 8, false);

        imshow("Threshold", thesholdFrame);
        //imshow("HSV", hsvFrame);
        imshow("Camera", frame);
    }

}

Can any of you try and run this to see if it works? Keep in mind that I am new to OpenCV.

edit retag flag offensive close merge delete

Comments

2

becarefull findContour in opencv 2.4 change input image (thesholdFrame). it is not written in opencv 3 doc but try something like this :

Mat cpythesholdFrame=thesholdFrame.clone();
findContours(cpythesholdFrame, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

move waitKey(10); just after imshow("Camera", frame);

LBerger gravatar imageLBerger ( 2017-01-02 21:29:04 -0600 )edit

Just a general comment: you can find here the general webpage for all the OpenCV version documentation. It is important as there could be minor subtle changes between versions.

Since OpenCV 3.2, findContours should no more modify the input image.

Eduardo gravatar imageEduardo ( 2017-01-03 09:48:24 -0600 )edit

@LBerger I tried adjusting my code to match what you have there and it is displaying the same thing.It isn't detecting my hand at all. It keeps wanting to detect random parts of the wall. Do you know any approximate HSV min and max values that I should use to detect certain skin colours? Maybe my HSV values aren't done correctly. I do remember the values that worked perfectly once but aren't working anymore. Currently I am in front of a white wall, with nothing but my hand and using values of H(0,180), S(0,220),V(190,255). Where the first value is the MIN value and the second one is the max value.

FShiwani gravatar imageFShiwani ( 2017-01-05 18:13:07 -0600 )edit

if you want to find HSV value in a rect you can build this source file : give an image as parameter select a rect using mouse and press g. Values are displayed in console

LBerger gravatar imageLBerger ( 2017-01-06 03:39:42 -0600 )edit
1

@berak like @Eduardo said in opencv 3.2 there is no problem. i have tested using this prrogram

Mat test=imgCtr.clone();
findContours(imgCtr,contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
Mat dd;
subtract(test,imgCtr,dd,Mat(),CV_32S);
cout << countNonZero(dd)<<endl;

it is always 0. May be a warning could be inserted in doc now Since opencv 3.2 Source image is not modified by this function

may be this commit changes doc

LBerger gravatar imageLBerger ( 2017-01-08 03:07:28 -0600 )edit

@LBerger , ah, you're right (removed the other answer)

berak gravatar imageberak ( 2017-01-08 03:57:34 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-01-02 23:52:22 -0600

updated 2017-01-09 04:29:19 -0600

Try this code. It definitely works with a white background or any other color that isn't hard to separate from skin color using HSV thresholding. If you don't want it to work for only certain backgrounds then you should use some sort of skin detector first to get just the hand region and then find the contour.

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;

int H_MIN = 0;
int H_MAX = 255;
int S_MIN = 0;
int S_MAX = 255;
int V_MIN = 0;
int V_MAX = 255;
void on_trackbar(int, void*)
 {

 }

void createTrackbars()
{
 //create window for trackbars
 namedWindow("Trackbars", 0);
 //create memory to store trackbar name on window
 char TrackbarName[50];
 sprintf(TrackbarName, "H_MIN", H_MIN);
 sprintf(TrackbarName, "H_MAX", H_MAX);
 sprintf(TrackbarName, "S_MIN", S_MIN);
 sprintf(TrackbarName, "S_MAX", S_MAX);
 sprintf(TrackbarName, "V_MIN", V_MIN);
 sprintf(TrackbarName, "V_MAX", V_MAX);
 //create trackbars and insert them into window to change H,S,V values

 createTrackbar("H_MIN", "Trackbars", &H_MIN, H_MAX, on_trackbar);
 createTrackbar("H_MAX", "Trackbars", &H_MAX, H_MAX, on_trackbar);
 createTrackbar("S_MIN", "Trackbars", &S_MIN, S_MAX, on_trackbar);
 createTrackbar("S_MAX", "Trackbars", &S_MAX, S_MAX, on_trackbar);
 createTrackbar("V_MIN", "Trackbars", &V_MIN, V_MAX, on_trackbar);
 createTrackbar("V_MAX", "Trackbars", &V_MAX, V_MAX, on_trackbar);
}

int main()
{
 Mat frame, HSV, thresh;
 Mat structuringElement3x3 = getStructuringElement(MORPH_RECT, Size(3, 3));

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

 createTrackbars();

 VideoCapture capture(1);
 if (!capture.isOpened())
 {
     return -1;
 }

 for (;;)
 {
     capture >> frame;
     imshow("Original_frame", frame);

     cvtColor(frame, HSV, CV_BGR2HSV);
     imshow("HSV_image", HSV);

     inRange(HSV, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), thresh);

     imshow("threshold_image", thresh);

     erode(thresh, thresh, structuringElement3x3);
     erode(thresh, thresh, structuringElement3x3);
     dilate(thresh, thresh, structuringElement3x3);
     dilate(thresh, thresh, structuringElement3x3);
     dilate(thresh, thresh, structuringElement3x3);

     Mat result(thresh.size(), CV_8UC3, Scalar(0.0, 0.0, 0.0));
     findContours(thresh, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
     int largest_area = 0; int largest_contour_index = 0;
     for (int i = 0; i < contours.size(); i++)
     {
         /*double area = contourArea(contours[i]);
         if (area > largest_area)
         {
             largest_area = area;
             largest_contour_index = i;
         }*/
        drawContours(result, contours, i, Scalar(255.0, 255.0, 255.0), 1, 8);
     }

     //drawContours(result, contours, largest_contour_index, Scalar(255.0, 255.0, 255.0), 1, 8);
     imshow("contours_image", result);

     if (waitKey(30) >= 0)
        break;
 }

 return 0;
}

I've commented out the largest contour area part because I found for lighting conditions I tested it in, the code worked better without that part. You can experiment with that and the morphological operations to see what suits your condition the best.

Seen my answer here to a similar question to see the results of this code for static images.

edit flag offensive delete link more

Comments

I appreciate the response. The code you posted above builds perfectly fine, however as soon as I run it I get the following errors:

The thread 0x2d2c has exited with code -1 (0xffffffff).
The thread 0x4bf8 has exited with code -1 (0xffffffff).
The thread 0x3f30 has exited with code -1 (0xffffffff).
The program '[13516] FingerDetection.exe' has exited with code -1 (0xffffffff).
FShiwani gravatar imageFShiwani ( 2017-01-05 08:47:39 -0600 )edit

The only part of my code that returns -1 is the part that opens the camera. I was using a usb cam so used VideoCapture capture(1). It should be 0 if you're using the webcam. Maybe that's the issue?

abhijith gravatar imageabhijith ( 2017-01-05 22:43:01 -0600 )edit

Ah. That seems to have fixed it. I appreciate the response.

FShiwani gravatar imageFShiwani ( 2017-01-07 16:53:03 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-01-02 19:19:40 -0600

Seen: 772 times

Last updated: Jan 09 '17