예제 #1
0
void MyGesture::getFingerTips(MyInputImgStruct *m){
/***
 *@DOC:  Gets which of the remaining Defect points are the finger tips
 * and returns it into the vector FingerTips
**/
	FingerTips.clear();
	int i = 0;
	vector<Vec4i>::iterator d = Defects[cIdx].begin();
	while(d != Defects[cIdx].end())
	{
		Vec4i& v = (*d);
		int startidx = v[0];
		Point ptStart(contours[cIdx][startidx]);
		int endidx = v[1];
		Point ptEnd(contours[cIdx][endidx]);
		int faridx = v[2];
		Point ptFar(contours[cIdx][faridx]);
		if(i==0){
			FingerTips.push_back(ptStart);
			i++;
		}
		FingerTips.push_back(ptEnd);
		d++;
		i++;
	}//ENDOF while()
	if(FingerTips.size() == 0)
	{
		checkForOneFinger(m);
	}
} //ENDOF Method: getFingerTips(MyInputImgStruct *m)
void condefects(vector<Vec4i>convexityDefectsSet, vector<Point> mycontour, Mat& drawing){
	for (int cDefIt = 0; cDefIt < convexityDefectsSet.size(); cDefIt++)
	{
		int startIdx = convexityDefectsSet[cDefIt].val[0]; Point ptStart(mycontour[startIdx]);
		int endIdx = convexityDefectsSet[cDefIt].val[1];	Point ptEnd(mycontour[endIdx]);
		int defectPtIdx = convexityDefectsSet[cDefIt].val[2]; Point ptFar(mycontour[defectPtIdx]);
		double depth = (double)convexityDefectsSet[cDefIt].val[3] / 256.0f;  // see documentation link below why this

		circle(drawing, ptStart, 5, CV_RGB(255, 0, 0), 2, 8);
		circle(drawing, ptEnd, 5, CV_RGB(255, 0, 0), 2, 8);
		circle(drawing, ptFar, 5, CV_RGB(255, 0, 0), 2, 8);
		// do something with *contour[defectPtIdx]*.. This is e.g. the defect point.

	}
}
예제 #3
0
void MyGesture::eleminateDefects(MyInputImgStruct *m){
/***
 * @DOC: Takes all the defect points into vector d. Loops through d and
 * measures the P2P distance between the Defect Points and decides whether
 * the Point will be dismissed or kept based on l>0.4lbb and Theta>85'
**/

	int tolerance = bRect_Height/5;
	float angleTol = 95;
	vector<Vec4i> newDefects;
	int startidx, endidx, faridx;
	vector<Vec4i>::iterator d = Defects[cIdx].begin();
	while(d != Defects[cIdx].end())
	{
		Vec4i& v = (*d);
		startidx = v[0];
		Point ptStart(contours[cIdx][startidx]);
		endidx = v[1];
		Point ptEnd(contours[cIdx][endidx]);
		faridx = v[2];
		Point ptFar(contours[cIdx][faridx]);

		if((distanceP2P(ptStart, ptFar) > tolerance) &&
				(distanceP2P(ptEnd, ptFar) > tolerance) &&
						(getAngle(ptStart, ptFar, ptEnd) < angleTol)){
			if(ptEnd.y > (bRect.y + bRect.height - bRect.height/4)) {/*Do Nothing*/}
			else if(ptStart.y > (bRect.y + bRect.height - bRect.height/4)) {/*Do Nothing*/}
			else {
				newDefects.push_back(v);
			}
		}
		d++;
	}//ENDOF While()
	numOfDefects = newDefects.size();
	Defects[cIdx].swap(newDefects);
	removeRedundantEndPoints(Defects[cIdx], m);
} //ENDOF Method: eleminateDefects(MyInputImgStruct *m)
void HandDetector::FindConvexityDefects(vector<Vec4i> ConvexityDefectSet, vector<Point> HandContour, Mat& LiveFrame, Point2f COM, int TiltAngle)
{
	vector<Point> FingerTips;
	
	Point2f HandCenter;
	float radius;
	int fingers=0;

	//minEnclosingCircle(HandContour,HandCenter,radius);
	//Rect contourRect = boundingRect(HandContour);
	//circle(LiveFrame,HandCenter,10,CV_RGB(0,0,255),2,8);
	//rectangle(LiveFrame, contourRect, Scalar(0,0,255), 3);
	//vector<Point> palmCircle;
	for (int i = 0; i < ConvexityDefectSet.size(); i++) 
	{

		int startId = ConvexityDefectSet[i].val[0];
		Point ptStart(HandContour[startId]);

		int endId = ConvexityDefectSet[i].val[1]; 
		Point ptEnd(HandContour[endId]);

		int farId = ConvexityDefectSet[i].val[2]; 
		Point ptFar(HandContour[farId]);

		double depth = (double)((ConvexityDefectSet[i].val[3]) / 256); //for getting real pixel values

		//cout << "depth" << depth << endl;
		//display start points
		//circle(original,ptStart,5,CV_RGB(255,0,0),2,8);
		//display all end points
		//circle(original, ptEnd, 5, CV_RGB(255, 255, 0), 2, 8);
		//display all far points
		//circle(LiveFrame,ptFar,5,CV_RGB(255,255,0),2,8);

		//circle(LiveFrame, HandCenter, radius, cv::Scalar(0,255,255),2);
		if (depth > 10 && ptStart.y < COM.y)//
		{
			circle(LiveFrame,ptStart,5,CV_RGB(255,0,0),2,8);
			//circle(LiveFrame, ptStart, 4, CV_RGB(255, 0,0), 4);
			FingerTips.push_back(ptStart);
			fingers++;
			//palmCircle.push_back(ptStart);
						
		}
	}
		
	if(mMouseControl)
	{
		InitMouseControl(LiveFrame,FingerTips,COM,TiltAngle);
	}
	if(mSwipeON)
	{
		Point tempCOM;
		tempCOM.x = COM.x;
		tempCOM.y = COM.y;
		mSwipeGesture.SwipeInit(tempCOM, LiveFrame);
	}

	//cout<<"Fingers = "<<fingers<<endl;
}
Mat CameraInteraction::Testmm(Mat frame){




            vector<vector<Point> > contours;


            //Update the current background model and get the foreground
            if(backgroundFrame>0)
            {bg.operator ()(frame,fore);backgroundFrame--;}
            else
            {bg.operator()(frame,fore,0);}

            //Get background image to display it
            bg.getBackgroundImage(back);


            //Enhance edges in the foreground by applying erosion and dilation
            erode(fore,fore,Mat());
            dilate(fore,fore,Mat());


            //Find the contours in the foreground
            findContours(fore,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
            for(int i=0;i<contours.size();i++)
                //Ignore all small insignificant areas
                if(contourArea(contours[i])>=5000)
                {
                    //Draw contour
                    vector<vector<Point> > tcontours;
                    tcontours.push_back(contours[i]);
                    drawContours(frame,tcontours,-1,cv::Scalar(0,0,255),2);

                    //Detect Hull in current contour
                    vector<vector<Point> > hulls(1);
                    vector<vector<int> > hullsI(1);
                    convexHull(Mat(tcontours[0]),hulls[0],false);
                    convexHull(Mat(tcontours[0]),hullsI[0],false);
                    drawContours(frame,hulls,-1,cv::Scalar(0,255,0),2);

                    //Find minimum area rectangle to enclose hand
                    RotatedRect rect=minAreaRect(Mat(tcontours[0]));

                    //Find Convex Defects
                    vector<Vec4i> defects;
                    if(hullsI[0].size()>0)
                    {
                        Point2f rect_points[4]; rect.points( rect_points );
                        for( int j = 0; j < 4; j++ )
                            line( frame, rect_points[j], rect_points[(j+1)%4], Scalar(255,0,0), 1, 8 );
                        Point rough_palm_center;
                        convexityDefects(tcontours[0], hullsI[0], defects);
                        if(defects.size()>=3)
                        {
                            vector<Point> palm_points;
                            for(int j=0;j<defects.size();j++)
                            {
                                int startidx=defects[j][0]; Point ptStart( tcontours[0][startidx] );
                                int endidx=defects[j][1]; Point ptEnd( tcontours[0][endidx] );
                                int faridx=defects[j][2]; Point ptFar( tcontours[0][faridx] );
                                //Sum up all the hull and defect points to compute average
                                rough_palm_center+=ptFar+ptStart+ptEnd;
                                palm_points.push_back(ptFar);
                                palm_points.push_back(ptStart);
                                palm_points.push_back(ptEnd);
                            }

                            //Get palm center by 1st getting the average of all defect points, this is the rough palm center,
                            //Then U chose the closest 3 points ang get the circle radius and center formed from them which is the palm center.
                            rough_palm_center.x/=defects.size()*3;
                            rough_palm_center.y/=defects.size()*3;
                            Point closest_pt=palm_points[0];
                            vector<pair<double,int> > distvec;
                            for(int i=0;i<palm_points.size();i++)
                                distvec.push_back(make_pair(dist(rough_palm_center,palm_points[i]),i));
                            sort(distvec.begin(),distvec.end());

                            //Keep choosing 3 points till you find a circle with a valid radius
                            //As there is a high chance that the closes points might be in a linear line or too close that it forms a very large circle
                            pair<Point,double> soln_circle;
                            for(int i=0;i+2<distvec.size();i++)
                            {
                                Point p1=palm_points[distvec[i+0].second];
                                Point p2=palm_points[distvec[i+1].second];
                                Point p3=palm_points[distvec[i+2].second];
                                soln_circle=circleFromPoints(p1,p2,p3);//Final palm center,radius
                                if(soln_circle.second!=0)
                                    break;
                            }

                            //Find avg palm centers for the last few frames to stabilize its centers, also find the avg radius
                            palm_centers.push_back(soln_circle);
                            if(palm_centers.size()>10)
                                palm_centers.erase(palm_centers.begin());

                            Point palm_center;
                            double radius=0;
                            for(int i=0;i<palm_centers.size();i++)
                            {
                                palm_center+=palm_centers[i].first;
                                radius+=palm_centers[i].second;
                            }
                            palm_center.x/=palm_centers.size();
                            palm_center.y/=palm_centers.size();
                            radius/=palm_centers.size();

                            //Draw the palm center and the palm circle
                            //The size of the palm gives the depth of the hand
                            circle(frame,palm_center,5,Scalar(144,144,255),3);
                            circle(frame,palm_center,radius,Scalar(144,144,255),2);

                            //Detect fingers by finding points that form an almost isosceles triangle with certain thesholds
                            int no_of_fingers=0;
                            for(int j=0;j<defects.size();j++)
                            {
                                int startidx=defects[j][0]; Point ptStart( tcontours[0][startidx] );
                                int endidx=defects[j][1]; Point ptEnd( tcontours[0][endidx] );
                                int faridx=defects[j][2]; Point ptFar( tcontours[0][faridx] );
                                //X o--------------------------o Y
                                double Xdist=sqrt(dist(palm_center,ptFar));
                                double Ydist=sqrt(dist(palm_center,ptStart));
                                double length=sqrt(dist(ptFar,ptStart));

                                double retLength=sqrt(dist(ptEnd,ptFar));
                                //Play with these thresholds to improve performance
                                if(length<=3*radius&&Ydist>=0.4*radius&&length>=10&&retLength>=10&&max(length,retLength)/min(length,retLength)>=0.8)
                                    if(min(Xdist,Ydist)/max(Xdist,Ydist)<=0.8)
                                    {
                                        if((Xdist>=0.1*radius&&Xdist<=1.3*radius&&Xdist<Ydist)||(Ydist>=0.1*radius&&Ydist<=1.3*radius&&Xdist>Ydist))
                                            line( frame, ptEnd, ptFar, Scalar(0,255,0), 1 ),no_of_fingers++;
                                    }


                            }

                            no_of_fingers=min(5,no_of_fingers);
                            qDebug()<<"NO OF FINGERS: "<<no_of_fingers;
                            //mouseTo(palm_center.x,palm_center.y);//Move the cursor corresponding to the palm
                            if(no_of_fingers<4)//If no of fingers is <4 , click , else release
//                                mouseClick();
                                qDebug()<<"Test";
                            else
//                                mouseRelease();
                                qDebug()<<"Hola";

                        }
                    }

                }
            if(backgroundFrame>0)
                putText(frame, "Recording Background", cvPoint(30,30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, cvScalar(200,200,250), 1, CV_AA);
//            imshow("Framekj",frame);
//            imshow("Background",back);
return frame;

}