Ask Your Question

Revision history [back]

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 particular 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));

 int largest_area = 0; int largest_contour_index = 0;
 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);

     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);
}

Oh and, 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.

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 particular 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));

 int largest_area = 0; int largest_contour_index = 0;
 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);

     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);
}

Oh and, 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.

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));

 int largest_area = 0; int largest_contour_index = 0;
 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);

     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);
}

Oh and, 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.

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));

 int largest_area = 0; int largest_contour_index = 0;
 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);

     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);
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.

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));

 int largest_area = 0; int largest_contour_index = 0;
 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.