void gestureTracker::detectGesture(Mat hand_roi, string rl)
{
    Mat thresh;
    Mat img = Mat::zeros( hand_roi.size(), CV_8UC3 );
    img = hand_roi.clone();

    Size max = hand_roi.size();
    int max_x = max.width;
    int max_y = max.height;

    double palm_dist = 0.0;

    Rect thresh_roi = Rect(3*max_x/7, 3*max_y/7, max_x/7, max_y/7);
    Scalar avg = cv::mean(img(thresh_roi));
    //cerr << avg[0] << endl;

    int max_dist = avg[0] + 1400;
    int min_dist = 0;
    if(avg[0] >= 1400)
        min_dist = avg[0] - 1400;

    for (int i = 0; i < max_y; i++)
    {
        for (int j = 0; j < max_x; j++)
        {
            int val = (int)img.at<short>(i,j);
            if(val <= min_dist)
                img.at<short>(i,j) = 0;
            else if(val >= max_dist)
                img.at<short>(i,j) = 0;
        }
    }

    img.convertTo(img, CV_8UC3);

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours( img, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    /// Draw contours
    double max_area = 0.0;
    int idx = -1;
    Mat drawing = Mat::zeros( img.size(), CV_8UC3 );
    //cerr << contours.size() << endl;
    for( int i = 0; i < contours.size(); i++ )
    {
        double area = contourArea(contours[i]);
        if(area > max_area )
        {
            max_area = area;
            idx = i;
        }
    }

    Scalar white = Scalar( 255, 255, 255 );
    Scalar yellow = Scalar( 0, 255, 255 );
    Scalar purple = Scalar( 255, 0, 255 );
    Scalar blue = Scalar( 255, 0, 0 );
    Scalar red = Scalar( 0, 0, 255 );
    Scalar green = Scalar( 0, 255, 0 );

    if(idx != -1)
    {
        //drawContours( drawing, contours, idx, white, 1, 8, vector<Vec4i>(), 0, Point() );
        //imshow(rl, drawing);
        //cv::waitKey(20);
    }


    if(idx != -1)
    {
        if (contours[idx].size() <= 5)
            return;

        //cerr << idx << endl;
        // convex hull for drawing (Points)
        vector<vector<Point> > hullp(contours[idx].size());
        // convex Hull for defects (ints)
        vector<vector<int> > hulli(contours[idx].size());
        vector<vector<Point> > hull_points(contours[idx].size());
        vector<vector<Point> > defect_points(contours[idx].size());

        convexHull( Mat(contours[idx]), hulli[0], false );
        convexHull( Mat(contours[idx]), hullp[0], false );

        /*
        for(int i = 0; i < hullp[0].size(); i++)
        	circle( drawing, hullp[0][i], 5, blue, -1 );
        */

        vector<vector<Vec4i> > defects(contours[idx].size());
        if (hulli[0].size() > 2 && contours[idx].size() > 3)
        {
            convexityDefects(contours[idx], hulli[0], defects[0]);

            Point palm;
            double x_sum = 0.0;
            double y_sum = 0.0;
            for(int i = 0; i < defects[0].size(); i++)
            {
                for(int j = 0; j < 3; j++)
                {
                    x_sum += contours[idx][defects[0][i][j]].x;
                    y_sum += contours[idx][defects[0][i][j]].y;
                }
            }

            palm.x = (x_sum / defects[0].size()) / 3.0;
            palm.y = (y_sum / defects[0].size()) / 3.0;

            if(rl == "right")
            {
                r_hand_palm_x_filter.add(palm.x);
                r_hand_palm_y_filter.add(palm.y);
                palm.x = r_hand_palm_x_filter.average();
                palm.y = r_hand_palm_y_filter.average();
            }
            else
            {
                l_hand_palm_x_filter.add(palm.x);
                l_hand_palm_y_filter.add(palm.y);
                palm.x = l_hand_palm_x_filter.average();
                palm.y = l_hand_palm_y_filter.average();
            }

            // max = 20 ish, min  = 7 ish
            palm_dist = (hand_roi.at<short>(palm.y, palm.x)/65536.0)*100.0;
            cerr << "Palm: " << palm_dist << endl;

            circle(drawing, palm, 5, green, -1);
            double avg_dist = 0.0;
            for(int i = 0; i < defects[0].size(); i++)
            {
                int idx_0 = defects[0][i][0];
                int idx_1 = defects[0][i][1];
                int idx_2 = defects[0][i][2];
                defect_points[i].push_back(contours[idx][idx_2]);

                /*
                circle(drawing, contours[idx][idx_0], 5, yellow, -1);
                circle(drawing, contours[idx][idx_1], 5, blue, -1);
                circle(drawing, contours[idx][idx_2], 5, red, -1);
                line(drawing, contours[idx][idx_2], contours[idx][idx_0], purple, 1);
                line(drawing, contours[idx][idx_2], contours[idx][idx_1], purple, 1);
                */

                int tip_x = contours[idx][idx_0].x;
                int tip_y = contours[idx][idx_0].y;

                int defect_x = contours[idx][idx_2].x;
                int defect_y = contours[idx][idx_2].y;

                double dist = 0.0;
                dist = sqrt(pow((tip_x - defect_x), 2) + pow((tip_y - defect_y), 2));
                avg_dist += dist;
            }

            if(defects[0].size() > 0)
            {
                avg_dist = avg_dist / defects[0].size();
                // normalize for fingers
                avg_dist = avg_dist / 20.0;
                cerr << rl << " " << defects[0].size()/3 - 2 << endl;

                std_msgs::Float64 state_msg;
                if(rl == "right")
                {
                    r_hand_state_filter.add(avg_dist - 0.3);
                    state_msg.data = (r_hand_state_filter.average());
                    r_hand_state_pub.publish(state_msg);
                    //cerr << "distance R: " << r_hand_state_filter.average() << endl;

                }
                else
                {

                    l_hand_state_filter.add(avg_dist - 0.3);
                    state_msg.data = (l_hand_state_filter.average());
                    l_hand_state_pub.publish(state_msg);
                    //cerr << "distance L: " << l_hand_state_filter.average() << endl;
                }
            }

        }
        /*
        try{
        if(rl == "right")
        	imshow(rl + "hand", drawing);
        else
        	imshow(rl + "hand", drawing);
        }
        catch(...){return;}
        */

        cv::waitKey(20);
        //threshold(img, thresh, 30, 255, CV_THRESH_BINARY_INV);

    }

}
void HandDetector::FindConvexHull(Mat& LiveFrame, Mat SkinThreshold)
{
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	Point2f COM; //Center of Mass
	int TiltAngle = 0;
			
	int LargestArea = 0;
	int LargestAreaIndex = -1;

	cv::findContours(SkinThreshold,contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

	vector<vector<Point>> hull(contours.size());

	vector<vector<int> > inthull(contours.size());
	vector<vector<Vec4i> > defects(contours.size()); 

	
	for(int i=0;i<contours.size();++i)
	{
		convexHull(Mat(contours[i]),hull[i],false);
		convexHull(Mat(contours[i]), inthull[i], false);
		if (inthull[i].size()>3)
			convexityDefects(contours[i], inthull[i], defects[i]);

	}

	
	for(int i=0;i<contours.size();++i)
	{
		double area = cv::contourArea(contours[i],false);
		if(area > LargestArea)
			
			{
				LargestArea = area;
				LargestAreaIndex = i;
			}
	}
	if(contours.size() > 0 && LargestArea > 10000 && LargestArea < 90000 && !mObjectTrackFlag)
	{
		//cv::drawContours(frame,contours,id,CV_RGB(0,255,0),2,8,hierarchy);
		drawContours(LiveFrame, hull ,LargestAreaIndex, CV_RGB(0, 255, 0), 2, 8, hierarchy);
		drawContours(LiveFrame, contours, LargestAreaIndex, CV_RGB(0, 0, 255), 2, 8, hierarchy);
		//kCurvature(contours,hull,inthull,LiveFrame);
		//cout<<"\nlargest Area : "<<largest_area;
		Moments moment;
		moment = moments( contours[LargestAreaIndex], false ); 
		
		///  Get the mass centers:
		COM = Point2f( moment.m10/moment.m00 , moment.m01/moment.m00 ); 
		circle(LiveFrame,COM,4,Scalar(255,0,0),2);
		//TiltAngle = CalculateHandTilt(moment.m11,moment.m20,moment.m02);
		//cout<<"\n Tilt Angle : "<<TiltAngle;
		//cout<<GetOrientation(contours[LargestAreaIndex],LiveFrame)<<"\n";
		//cout<<"\n"<<COM.x<<" "<<COM.y;
		FindConvexityDefects(defects[LargestAreaIndex], contours[LargestAreaIndex], LiveFrame,COM, TiltAngle);

		
	}
	else if(contours.size() > 0 && LargestArea > 10 && LargestArea < 30000 && mObjectTrackFlag)
	{
		drawContours(LiveFrame, hull ,LargestAreaIndex, CV_RGB(0, 255, 0), 2, 8, hierarchy);
		drawContours(LiveFrame, contours, LargestAreaIndex, CV_RGB(0, 0, 255), 2, 8, hierarchy);
		Moments moment;
		moment = moments( contours[LargestAreaIndex], false ); 
		
		///  Get the mass centers:
		COM = Point2f( moment.m10/moment.m00 , moment.m01/moment.m00 ); 
		circle(LiveFrame,COM,4,Scalar(255,0,0),2);
		Draw(COM.x,COM.y);
		
	}
	else if(mSwipeON)
	{
		mSwipeGesture.Reset();
	}
}