chronojump r425 - trunk/src/angle



Author: xaviblas
Date: Mon Nov  3 17:24:17 2008
New Revision: 425
URL: http://svn.gnome.org/viewvc/chronojump?rev=425&view=rev

Log:
kneeAngle 1.5.1
-working on opencv1.1 and ubuntu 8.10 (Intrepid)
-zoom done
-threshold can be modified manually always
-can jump forward and backward
-on skin, at start or after forward or jump, ask if points are ok
-forward, jump is possible also when a skin marker failed
-code lot cleaner
-code of kneeabduction done


Modified:
   trunk/src/angle/kneeAngle.cpp
   trunk/src/angle/kneeAngleFunctions.cpp
   trunk/src/angle/kneeAngleUtil.cpp

Modified: trunk/src/angle/kneeAngle.cpp
==============================================================================
--- trunk/src/angle/kneeAngle.cpp	(original)
+++ trunk/src/angle/kneeAngle.cpp	Mon Nov  3 17:24:17 2008
@@ -23,7 +23,7 @@
  * Xavier de Blas 
  * xaviblas gmail com
  *
- * version: 1.4 (Oct, 28, 2008)
+ * version: 1.5.1 (Nov, 3, 2008)
  *
  */
 
@@ -86,10 +86,14 @@
  *
  * g++ -lcv -lcxcore -lhighgui -L(path to opencv library) kneeAngle.cpp -o kneeAngle
  *
- * for example
+ * for example: 
  * 
+ * Ubuntu Hoary (8.04) with opencv 1.0
  * g++ -lcv -lcxcore -lhighgui -L/usr/local/lib kneeAngle.cpp -o kneeAngle
  * 
+ * Ubuntu Intrepid (8.10) with opencv 1.1
+ * g++ `pkg-config --cflags opencv` kneeAngle.cpp -o kneeAngle `pkg-config --libs opencv`
+ *
  * command to run the file
  * ./kneeAngle "path to video file"
  *
@@ -118,10 +122,13 @@
 
 using namespace std;
 
+
+int menu(void);
+
 //config variables
 bool showContour = true;
 bool debug = false;
-int playDelay = 5; //milliseconds between photogrammes wen playing. Used as a waitkey. 
+int playDelay = 10; //milliseconds between photogrammes wen playing. Used as a waitkey. 
 			//not put values lower than 5 or the enter when executing will be the first pause
 			//eg: 5 (fast) 1000 (one second each photogramme)
 //int playDelayFoundAngle = 150; //as above, but used when angle is found. 
@@ -144,14 +151,10 @@
 bool showStickTheLinesBetweenSamePoints = true;
 bool showStickTheLinesBetweenDifferentPoints = true;
 bool showStickOnlyStartMinEnd = true;
-
 bool mixStickWithMinAngleWindow = true;
 
-//if true, don't analyse the pants angle, only the validation points on black pants
-bool onlyValidationBlack = false;
-
-bool onlyValidationSkin = false;
-
+int startAt = 1;
+enum { blackAndMarkers = 0, blackOnlyMarkers = 1, skinOnlyMarkers = 2 };
 
 int main(int argc,char **argv)
 {
@@ -161,33 +164,22 @@
 		exit(1);
 	}
 
-	//printf("argc: %d\n",argc);
-	int startAt = -1;
-	if(argc >= 3)
-		startAt = atoi(argv[2]);
-	if(argc == 4 && *argv[3] == 'b') {
-		onlyValidationBlack = true;
-		printf("only validation black!!\n");
-	}
-	if(argc == 4 && *argv[3] == 's') {
-		onlyValidationSkin = true;
-		printf("only validation skin!!\n");
-	}
-
 	CvCapture* capture = NULL;
 	capture = cvCaptureFromAVI(argv[1]);
 	if(!capture)
 	{
 		exit(0);
 	}
-
 	//int framesNumber = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
 	//printf("--%d--\n", framesNumber);
-			
+
+	
+	int programMode = menu();
+
+	/* initialization variables */
 	IplImage *frame=0,*frame_copy=0,*gray=0,*segmented=0,*edge=0,*temp=0,*output=0;
 	IplImage *segmentedValidationHoles=0;
 	IplImage *foundHoles=0;
-	//IplImage *foundHolesContour=0;
 	IplImage *result=0;
 	IplImage *resultStick=0;
 	int minwidth = 0;
@@ -196,17 +188,20 @@
 	bool foundAngleOneTime = false; //found angle at least one time on the video
 
 	double knee2Hip,knee2Toe,hip2Toe;
-	double theta, thetaHoles;
+	double thetaExpected, thetaMarked;
 	string text,angle;
-	double minTheta = 360;
-	double minThetaHoles = 360;
+	double minThetaExpected = 360;
+	double minThetaMarked = 360;
 	char buffer[15];
-	cvNamedWindow("result",1);
 
-//	cvNamedWindow("gray",1);//meu
-	cvNamedWindow("holes",1); //meu
-//	cvNamedWindow("foundHoles",1); //meu
-//	cvNamedWindow("output",1);
+	if(programMode == skinOnlyMarkers)
+		cvNamedWindow("skinOutput",1);
+	else {
+		cvNamedWindow("holes",1);
+		cvNamedWindow("result",1);
+	}
+	
+
 
 	int kneePointWidth = -1;
 	int toePointWidth = -1;
@@ -223,7 +218,6 @@
 	double fontSize = .4;
 	cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, fontSize, fontSize, 0.0, 1, fontLineType);
 	
-	char key;
 	bool shouldEnd = false;
 
 	//stick storage
@@ -232,8 +226,8 @@
 	CvSeq* kneeSeq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), stickStorage );
 	CvSeq* toeSeq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), stickStorage );
   
-	if(! onlyValidationBlack && ! onlyValidationSkin) {
-		sprintf(label, "    fps a_black a_holes [   diff diff(%)] kneeDif  a_supD  a_infD");
+	if(programMode == blackAndMarkers) {
+		sprintf(label, "    fps a_black a_holes [   diff diff(%%)] kneeDif  a_supD  a_infD");
 		printf("%s\n" ,label);
 	}
 
@@ -251,22 +245,36 @@
 	int forwardSuperSpeed = 200;
 	int forwardCount = 0;
 		
-	CvPoint hipHolesPoint = pointToZero();
-	CvPoint kneeHolesPoint = pointToZero();
-	CvPoint toeHolesPoint = pointToZero();
+	CvPoint hipMarked = pointToZero();
+	CvPoint kneeMarked = pointToZero();
+	CvPoint toeMarked = pointToZero();
 	CvPoint hipOld = pointToZero();
 	CvPoint kneeOld = pointToZero();
 	CvPoint toeOld = pointToZero();
 
-	int legHolesDist = 0;
-	int legHolesDistMax = 0;
+	int upLegMarkedDist = 0;
+	int upLegMarkedDistMax = 0;
+	int downLegMarkedDist = 0;
+	int downLegMarkedDistMax = 0;
+
+	int threshold;
+	int thresholdMax = 255;
+	int thresholdInc = 1;
+
+	int key;
+	bool jumpedFrames = false;
+	bool jumping = false;
 
-	int brightness = -1;
 
 	while(!shouldEnd) 
 	{
 		framesCount ++;
 				
+		/*
+		 * 1
+		 * GET FRAME AND FLOW CONTROL
+		 */
+
 		frame = cvQueryFrame(capture);
 		if(!frame)
 			break;
@@ -292,6 +300,19 @@
 				toeOld = pointToZero();
 			}
 		}
+		if(jumping) {
+				hipOld = pointToZero();
+				kneeOld = pointToZero();
+				toeOld = pointToZero();
+				jumping = false;
+		}
+
+
+		/* 
+		 * 2
+		 * CREATE IMAGES
+		 */
+
 
 		if( !frame_copy ) 
 			frame_copy = cvCreateImage( cvSize(frame->width,frame->height),IPL_DEPTH_8U, frame->nChannels );
@@ -301,170 +322,252 @@
 		else
 			cvFlip( frame, frame_copy, 0 );
 
+
 		if(!gray)
 		{
 			gray = 		cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
 			segmented =	cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
 			segmentedValidationHoles  =	cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1); //meu
 			foundHoles  =	cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3); //meu
-			//foundHolesContour  =	cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1); //meu
 			edge =	cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
 			temp = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
 			output = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
 			result = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
 			resultStick = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
+	
+			if(programMode == skinOnlyMarkers)
+				threshold = 150;
+			else {
+				cvCvtColor(frame_copy,gray,CV_BGR2GRAY);
+				threshold = calculateThresholdStart(gray);
+			}
 		}
 
 		cvSmooth(frame_copy,frame_copy,2,5,5);
 		cvCvtColor(frame_copy,gray,CV_BGR2GRAY);
+		CvRect maxrect;
+			
 
-		// detect brightness
-		if(brightness == -1) {
-			brightness = calculateBrightness(gray);
-			printf("brightness: %d\n", brightness);
-		}
+		/*
+		 * 3 
+		 * FIND THREE MARKER POINTS
+		 */
 
-		//created image like the contour but with holes and more (stores on segmentedValidationHoles)
-		//recommended 25,255
-		//high threshold (40-60) detects more black things (useful to not confuse a hole when is close to the border)
-		//low threshold (5-10) detects less black things
-		//if the image is bright, a hight threshold is perfect to nice detect the shapes without detecting shadows
-		//int threshold = 35;
-		//put threshold min depending on brightnesss
-		//eg: nora: brightness 85 -> threshold 30
-		//eg: 44_lluis_puerta_salt6_m.MOV: brightness 73 -> threshold 10
-	
-		//adjust better, because:
-		//12_carles_tejedor_salt3_m.MOV
-		//is bright:0, but if put thresh to 1 then detects bad. and to 10 is ok
-		//
-		//on the other side, 2_roger_miralles_salt3_m.MOV
-		//is really dark and it needs a thresh of 1 to work
-		//
-		//also it could be nice to have a thresh that detects three objects
-		//another option, could be to have the thresh 10 as really minimum and darker images are unsupported!
-		int threshold;
-		int briMax = 85;
-		int briMin = 65;
-//		int briZero = 50;
-		int thresMax = 30;
-		int thresMin = 10;
-		if(brightness >= briMax) 
-			threshold = thresMax;
-//		else if(brightness <= briZero)
-//			threshold = 10;
-		else if(brightness <= briMin)
-			threshold = thresMin;
-		else
-			threshold = brightness - briMin + thresMin;
 
-		int thresholdMax = 255;
+		if(programMode == skinOnlyMarkers) 
+		{
+			cvCvtColor(frame_copy,output,CV_BGR2GRAY);
+			cvThreshold(gray, output, threshold, thresholdMax,CV_THRESH_BINARY_INV);
+		
+			/*
+			hipOld = hipMarked;
+			kneeOld = kneeMarked;
+			toeOld = toeMarked;
+			*/
+				
+			CvSeq* seqHolesEnd = findHolesSkin(output, frame_copy, hipMarked, kneeMarked, toeMarked);
 
-		CvRect maxrect;
-		int thresholdInc = 1;
+			hipMarked = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 0); 
+			kneeMarked = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 1 ); 
+			toeMarked = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 2 ); 
+
+			cvCircle(frame_copy,hipMarked,2, CV_RGB(128,128,128),1,8,0);
+			cvCircle(frame_copy,kneeMarked,2, CV_RGB(128,128,128),1,8,0);
+			cvCircle(frame_copy,toeMarked,2, CV_RGB(128,128,128),1,8,0);
 			
-		//at first photogram if onlyValidationSkin, ask user for the points
-		//don't do like this, go to another method and have the flow there
-		//also the same for onlyValidationBlack
-		if(onlyValidationSkin) {
-			if(hipSkin.x == 0  ) {
+			//if frame before nothing was detected (maybe first frame or after a forward or jump
+			//OR a point in this frame was not detected
+			if(
+					(pointIsNull(hipOld) && pointIsNull(kneeOld) && pointIsNull(toeOld)) ||
+					(pointIsNull(hipMarked) || pointIsNull(kneeMarked) || pointIsNull(toeMarked)) ) 
+			{
+				hipMouse = hipMarked;
+				kneeMouse = kneeMarked;
+				toeMouse = toeMarked;
+
 				cvNamedWindow( "toClick", 1 );
-				cvShowImage("toClick", gray);
+				cvShowImage("toClick", frame_copy);
+				mouseCanMark = true;
 				cvSetMouseCallback( "toClick", on_mouse, 0 );
-				printf("Please, mark hip point, then knee, then toe, and finally press any key\n"); 
-				int c = cvWaitKey(0);
-				printf("hip: (%d,%d), knee: (%d,%d), toe:(%d,%d)\n", 
-						hipSkin.x, hipSkin.y, kneeSkin.x, kneeSkin.y, toeSkin.x, toeSkin.y);
+				
+				cvCvtColor(frame_copy,output,CV_BGR2GRAY);
+				cvThreshold(gray, output, threshold, thresholdMax,CV_THRESH_BINARY_INV);
+				cvShowImage("skinOutput", output);
+					
+				printf("\nFrame: %d H(%d,%d), K(%d,%d), T(%d,%d)\n", framesCount, hipMarked.x, hipMarked.y, 
+						kneeMarked.x, kneeMarked.y, toeMarked.x, toeMarked.y);
+
+
+				if(pointIsNull(hipMarked) || pointIsNull(kneeMarked) || pointIsNull(toeMarked)) {
+					printf("** Please mark:");
+					if(pointIsNull(hipMarked))
+						printf(" HIP ");
+					if(pointIsNull(kneeMarked))
+						printf(" KNEE ");
+					if(pointIsNull(toeMarked))
+						printf(" TOE ");
+					printf("on 'toClick' window **\n");
+				}
+				
+				printf("Press 'p' when done.\n");
+				printf("Optionally:\n");
+				printf("\tReMark hip 'h', knee 'k', toe 't'\n"); 
+				printf("\tChange threshold: %d ('+' increase, '-' decrease)\n", threshold); 
+				printf("\tOthers: Zoom 'z', forward 'f', Forward 'F', jump 'j', quit program 'q'\n\n"); 
 
-				cvNamedWindow( "HolesBri", 1 );
-				int thresholdSkin = 150;
 				bool done = false;
+				IplImage* imgZoom;
 				do {
-					cvThreshold(gray,segmentedValidationHoles, thresholdSkin, thresholdMax,CV_THRESH_BINARY_INV);
-					cvShowImage("HolesBri", segmentedValidationHoles);
-					printf("threshold: %d ('+' increase, '-' decrease, 'q' done)\n", thresholdSkin); 
+					cvCvtColor(frame_copy,output,CV_BGR2GRAY);
+					cvThreshold(gray, output, threshold, thresholdMax,CV_THRESH_BINARY_INV);
+					
 					key = (char) cvWaitKey(0);
-					if(key == 'q' || key == 'Q' )
+					if(key == 'p' )
 						done  = true;
-					else if(key == '+')
-						thresholdSkin ++;
+					else if(key == 'q') {
+						done = true;
+						shouldEnd = true;
+					} else if(key == 'z') {
+						if(zoomed) {
+							cvDestroyWindow("zoomed");
+							cvReleaseImage(&imgZoom);
+							zoomed = false;
+							cvSetMouseCallback( "toClick", on_mouse, 0 );
+						} else {
+							imgZoom = zoomImage(frame_copy);
+							cvNamedWindow( "zoomed", 1 );
+							cvShowImage("zoomed", imgZoom);
+							zoomed = true;
+							cvSetMouseCallback( "zoomed", on_mouse, 0 );
+						}
+					}
+					else if(key == 'h') {
+						forceMouseHip = true;
+						printf("Remark Hip: ");
+					} else if(key == 'k') {
+						forceMouseKnee = true;
+						printf("Remark Knee: ");
+					} else if(key == 't') {
+						forceMouseToe = true;
+						printf("Remark Toe: ");
+					} else if(key == '+')
+						threshold ++;
 					else if(key == '-')
-						thresholdSkin --;
-				} while(! done);
-
-				//backward doesn't work:
-				//cvSetCaptureProperty( capture, CV_CAP_PROP_POS_FRAMES, 600.0 );
-				//cvSetCaptureProperty( capture, CV_CAP_PROP_POS_AVI_RATIO, .7 );
-				//http://opencv.willowgarage.com/wiki/HighGui
+						threshold --;
+					else if (key == 'f') {// 'FORWARD'
+						forward = true;
+						printf("forwarding ...\n");
+						done  = true;
+					} else if (key == 'F') { // 'FORWARD SUPER'
+						forwardSuper = true;
+						done  = true;
+						printf("super forwarding ...\n");
+					}
+					else if (key == 'j' || key == 'J') {
+						//jump frames
+						printf("current frame: %d. Jump to: ", framesCount);
+						int jump;
+						scanf("%d", &jump);
+
+						//works with opencv1.1!!
+						//now we can go back and forth
+						cvSetCaptureProperty( capture, CV_CAP_PROP_POS_FRAMES, jump-1 );
+
+						framesCount = jump;
+						hipOld = pointToZero();
+						kneeOld = pointToZero();
+						toeOld = pointToZero();
+
+						//when jumper is extending legs after maximal flexion, jump ends
+						//this jumped makes it didn't work, avoiding ending a jump
+						//when we have gone ('j') from a maximal flexion to the 1st frame again (extension)
+						jumpedFrames = true;
+						printf("jumping ...\n");
+					}
+					
+					cvThreshold(gray, output, threshold, thresholdMax,CV_THRESH_BINARY_INV);
 
+					sprintf(label, "frame: %d", framesCount);
+					cvPutText(output, label, cvPoint(10,frame->height-40),&font,CV_RGB(0,0,0));
 
-			} else {
-				cvThreshold(gray,segmentedValidationHoles, 150, thresholdMax,CV_THRESH_BINARY_INV);
-				cvCircle(segmentedValidationHoles,hipSkin,2, CV_RGB(255,0,0),1,8,0);
-				cvCircle(segmentedValidationHoles,kneeSkin,2, CV_RGB(255,0,0),1,8,0);
-				cvCircle(segmentedValidationHoles,toeSkin,2, CV_RGB(255,0,0),1,8,0);
-				cvShowImage("HolesBri", segmentedValidationHoles);
-				cvWaitKey(10);
-			}
+					sprintf(label, "threshold: %d", threshold);
+					cvPutText(output, label, cvPoint(10,frame->height-20),&font,CV_RGB(0,0,0));
 				
-			continue;			
-			//exit(0);
-		}
-
-		do {
-			cvThreshold(gray,segmentedValidationHoles, threshold, thresholdMax,CV_THRESH_BINARY_INV);
+					cvShowImage("skinOutput", output);
+				} while(! done);
+				
+				hipMarked = hipMouse;
+				kneeMarked = kneeMouse;
+				toeMarked = toeMouse;
+						
+				if(zoomed) {
+					cvDestroyWindow("zoomed");
+					cvReleaseImage(&imgZoom);
+					zoomed = false;
+				}
+				mouseCanMark = false;
+			}
+			
+		} 
+		else {
+			do {
+				cvThreshold(gray,segmentedValidationHoles, threshold, thresholdMax,CV_THRESH_BINARY_INV);
 
-			//create the largest contour image (stored on temp)
-			cvThreshold(gray,segmented,threshold,thresholdMax,CV_THRESH_BINARY_INV);
-			maxrect = findLargestContour(segmented, output, showContour);
+				//create the largest contour image (stored on temp)
+				cvThreshold(gray,segmented,threshold,thresholdMax,CV_THRESH_BINARY_INV);
+				maxrect = findLargestContour(segmented, output, showContour);
+
+				//search in output all the black places (pants) and 
+				//see if there's a hole in that pixel on segmentedValidationHoles
+				//if(programMode == blackAndMarkers || programMode == blackOnlyMarkers) {
+					CvSeq* seqHolesEnd = findHoles(
+							output, segmentedValidationHoles, foundHoles, frame_copy,  
+							maxrect, hipOld, kneeOld, toeOld);
+
+					hipMarked = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 0); 
+					kneeMarked = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 1 ); 
+					toeMarked = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 2 ); 
+				//}
+				threshold += thresholdInc;
+			} while(
+					(pointIsNull(hipMarked) || pointIsNull(kneeMarked) || pointIsNull(toeMarked))
+					&& threshold < 100);
 
-			//search in output all the black places (pants) and 
-			//see if there's a hole in that pixel on segmentedValidationHoles
-			if(onlyValidationSkin)
-				;
-			else {
-				CvSeq* seqHolesEnd = findHoles(
-						output, segmentedValidationHoles, foundHoles, frame_copy,  
-						maxrect, hipOld, kneeOld, toeOld);
+			threshold -= thresholdInc;
+		}
 			
-				hipHolesPoint = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 0); 
-				kneeHolesPoint = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 1 ); 
-				toeHolesPoint = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 2 ); 
-			}
-			threshold += thresholdInc;
-		} while(
-				(pointIsNull(hipHolesPoint) || pointIsNull(kneeHolesPoint) || pointIsNull(toeHolesPoint))
-				&& threshold < 100);
-
-		threshold -= thresholdInc;
-		hipOld = hipHolesPoint;
-		kneeOld = kneeHolesPoint;
-		toeOld = toeHolesPoint;
-
-
-		CvPoint hipPointBack;
-		CvPoint hipPoint;
-		CvPoint kneePointBack;
-		CvPoint kneePointFront;
-		CvPoint kneePoint;
-		CvPoint toePoint;
+		hipOld = hipMarked;
+		kneeOld = kneeMarked;
+		toeOld = toeMarked;
+
+
+		CvPoint hipExpected;
+		CvPoint kneeExpected;
+		CvPoint toeExpected;
 		//int area;
 
+		/*
+		 * 4
+		 * FIND POINTS ON BLACKANDMARKERS
+		 */
+
+		if(programMode == blackAndMarkers) {
+			CvPoint hipPointBack;
+			CvPoint kneePointBack;
+			CvPoint kneePointFront;
 
-		if( ! onlyValidationBlack) {
 			hipPointBack = findHipPoint(output,maxrect);
 
 			//provisionally ubicate hipPoint at horizontal 1/2
-			CvPoint hipPoint;
-			hipPoint.x = hipPointBack.x + (findWidth(output, hipPointBack, true) /2);
-			hipPoint.y = hipPointBack.y;
+			hipExpected.x = hipPointBack.x + (findWidth(output, hipPointBack, true) /2);
+			hipExpected.y = hipPointBack.y;
 
 			//knee	
 			kneePointFront = findKneePointFront(output,maxrect,hipPointBack.y);
 			kneePointBack = findKneePointBack(output,maxrect,hipPointBack.y, kneePointFront.x); //hueco popliteo
 
 			//toe
-			CvPoint toePoint = findToePoint(output,maxrect,kneePointFront.x,kneePointFront.y);
+			CvPoint toeExpected = findToePoint(output,maxrect,kneePointFront.x,kneePointFront.y);
 
 
 			foundAngle = false;
@@ -473,9 +576,9 @@
 			else {
 				if((double)(kneePointFront.x- hipPointBack.x) > 1.15*minwidth 
 						&&
-						upperSimilarThanLower(hipPoint, kneePointFront, toePoint)
-						&& !pointIsNull(hipHolesPoint) && !pointIsNull(kneeHolesPoint) && 
-						!pointIsNull(toeHolesPoint)
+						upperSimilarThanLower(hipExpected, kneePointFront, toeExpected)
+						&& !pointIsNull(hipMarked) && !pointIsNull(kneeMarked) && 
+						!pointIsNull(toeMarked)
 				  )
 					/* get lower this 1.25 because now we use mid leg to solve the hand problem and width is lower*/
 					/*1.25 again, because we use hip y again*/
@@ -492,12 +595,12 @@
 				if(kneePointWidth == -1) 
 					kneePointWidth = findWidth(output, kneePointFront, false);
 
-				kneePoint = kneePointInNearMiddleOfFrontAndBack(
+				kneeExpected = kneePointInNearMiddleOfFrontAndBack(
 						kneePointBack, kneePointFront, kneePointWidth, frame_copy);
 				cvCircle(frame_copy,kneePointBack,2, CV_RGB(128,128,128),1,8,0);
 				cvCircle(frame_copy,kneePointFront,2, CV_RGB(128,128,128),1,8,0);
 				cvLine(frame_copy,kneePointFront,kneePointBack,CV_RGB(128,128,128),1,1);
-				cvCircle(frame_copy,kneePoint,3, CV_RGB(255,255,0),1,8,0);
+				cvCircle(frame_copy,kneeExpected,3, CV_RGB(255,255,0),1,8,0);
 
 				// ------------ toe stuff ----------
 
@@ -509,53 +612,53 @@
 				 */
 
 				if(toePointWidth == -1) 
-					toePointWidth = findWidth(output, toePoint, false);
-				cvCircle(frame_copy,toePoint,2, CV_RGB(128,128,128),1,8,0);
+					toePointWidth = findWidth(output, toeExpected, false);
+				cvCircle(frame_copy,toeExpected,2, CV_RGB(128,128,128),1,8,0);
 
-				theta = findAngle(hipPoint, toePoint, kneePoint);
+				thetaExpected = findAngle2D(hipExpected, toeExpected, kneeExpected);
 
-				//fix toepoint.x at the 1/2 of the toe width
+				//fix toeExpected.x at the 1/2 of the toe width
 				//depending on kneeAngle
-				toePoint.x = fixToePointX(toePoint.x, toePointWidth, theta);
-				cvCircle(frame_copy,toePoint,3, CV_RGB(255,0,0),1,8,0);
+				toeExpected.x = fixToePointX(toeExpected.x, toePointWidth, thetaExpected);
+				cvCircle(frame_copy,toeExpected,3, CV_RGB(255,0,0),1,8,0);
 
 
 				// ------------ hip stuff ----------
 
-				//fix hipPoint ...
+				//fix hipExpected ...
 				cvCircle(frame_copy,hipPointBack,2, CV_RGB(128,128,128),1,8,0);
 
 				//... find at 3/2 of hip (surely under the hand) ...
-				//theta = findAngle(hipPoint, toePoint, kneePoint);
-				hipPoint = fixHipPoint1(output, hipPointBack.y, kneePoint, theta);
-				cvCircle(frame_copy,hipPoint,2, CV_RGB(128,128,128),1,8,0);
+				//thetaExpected = findAngle2D(hipExpected, toeExpected, kneeExpected);
+				hipExpected = fixHipPoint1(output, hipPointBack.y, kneeExpected, thetaExpected);
+				cvCircle(frame_copy,hipExpected,2, CV_RGB(128,128,128),1,8,0);
 
 				//... cross first hippoint with the knee-hippoint line to find real hippoint
-				hipPoint = fixHipPoint2(output, hipPointBack.y, kneePoint, hipPoint);
-				cvCircle(frame_copy,hipPoint,3, CV_RGB(255,0,0),1,8,0);
+				hipExpected = fixHipPoint2(output, hipPointBack.y, kneeExpected, hipExpected);
+				cvCircle(frame_copy,hipExpected,3, CV_RGB(255,0,0),1,8,0);
 
 
 				// ------------ flexion angle ----------
 
 				//find flexion angle
-				theta = findAngle(hipPoint, toePoint, kneePoint);
-				//double thetaBack = findAngle(hipPoint, toePoint, kneePointBack);
+				thetaExpected = findAngle2D(hipExpected, toeExpected, kneeExpected);
+				//double thetaBack = findAngle2D(hipExpected, toeExpected, kneePointBack);
 
 				//draw 2 main lines
-				cvLine(frame_copy,kneePoint,hipPoint,CV_RGB(255,0,0),1,1);
-				cvLine(frame_copy,kneePoint,toePoint,CV_RGB(255,0,0),1,1);
+				cvLine(frame_copy,kneeExpected,hipExpected,CV_RGB(255,0,0),1,1);
+				cvLine(frame_copy,kneeExpected,toeExpected,CV_RGB(255,0,0),1,1);
 
-				cvSeqPush( hipSeq, &hipPoint );
-				cvSeqPush( kneeSeq, &kneePoint );
-				cvSeqPush( toeSeq, &toePoint );
+				cvSeqPush( hipSeq, &hipExpected );
+				cvSeqPush( kneeSeq, &kneeExpected );
+				cvSeqPush( toeSeq, &toeExpected );
 
 
 				//find total area
 				//area = findTotalArea(gray, maxrect);
 
-				if(theta < minTheta)
+				if(thetaExpected < minThetaExpected)
 				{
-					minTheta = theta;
+					minThetaExpected = thetaExpected;
 					cvCopy(frame_copy,result);
 					lowestAngleFrame = framesCount;
 				}
@@ -569,137 +672,236 @@
 		}
 
 
-		if(pointIsNull(hipHolesPoint) || pointIsNull(kneeHolesPoint) || pointIsNull(toeHolesPoint))
-				thetaHoles = -1;
+		/*
+		 * 5
+		 * PRINT MARKERS RELATED INFO AND DO CALCULATIONS LIKE ANGLE
+		 */
+
+
+		if(pointIsNull(hipMarked) || pointIsNull(kneeMarked) || pointIsNull(toeMarked))
+			thetaMarked = -1;
 		else {
-			thetaHoles = findAngle(hipHolesPoint, toeHolesPoint, kneeHolesPoint);
-			if(thetaHoles < minThetaHoles) 
-				minThetaHoles = thetaHoles;
+			thetaMarked = findAngle2D(hipMarked, toeMarked, kneeMarked);
+			if(thetaMarked < minThetaMarked) 
+				minThetaMarked = thetaMarked;
 
 
-			cvRectangle(frame_copy,
-					cvPoint(maxrect.x,maxrect.y),
-					cvPoint(maxrect.x + maxrect.width, maxrect.y + maxrect.height),
-					CV_RGB(255,0,0),1,1);
+			if(programMode == blackAndMarkers)
+				cvRectangle(frame_copy,
+						cvPoint(maxrect.x,maxrect.y),
+						cvPoint(maxrect.x + maxrect.width, maxrect.y + maxrect.height),
+						CV_RGB(255,0,0),1,1);
 
+
+			/*
 			//print frame variation of distances of leg
 			//soon find abduction, and then real flexion angle
-			legHolesDist = getDistance(hipHolesPoint, kneeHolesPoint) + getDistance(toeHolesPoint, kneeHolesPoint);
-			if(legHolesDist > legHolesDistMax)
-				legHolesDistMax = legHolesDist;
-
-			sprintf(label, "legSize: %d(%.1f\%)", legHolesDist, relError(legHolesDistMax, legHolesDist));
-			cvPutText(frame_copy, label, cvPoint(frame->width-150, frame->height-20),&font,CV_RGB(255,255,255));
-
-				
-			sprintf(label, "frame: %d", framesCount);
-			cvPutText(frame_copy, label, cvPoint(10,frame->height-80),&font,CV_RGB(255,255,255));
+			*/
+			upLegMarkedDist = getDistance(hipMarked, kneeMarked);
+			if(upLegMarkedDist > upLegMarkedDistMax)
+				upLegMarkedDistMax = upLegMarkedDist;
+			downLegMarkedDist = getDistance(toeMarked, kneeMarked);
+			if(downLegMarkedDist > downLegMarkedDistMax)
+				downLegMarkedDistMax = downLegMarkedDist;
+
+			CvPoint HT;
+			HT.y = kneeMarked.y;
+			double verticalKVersusHT = (kneeMarked.y - toeMarked.y) / (double) (hipMarked.y-toeMarked.y) ;
+			HT.x = ((hipMarked.x - toeMarked.x) * verticalKVersusHT ) + toeMarked.x;
+
+			double kneeZetaSide = sqrt( pow(upLegMarkedDistMax,2) - pow(upLegMarkedDist,2) );
+			double htKneeMarked = getDistance (HT, kneeMarked);
+
+			double thetaABD = (180.0/M_PI)*atan( kneeZetaSide / (double) htKneeMarked );
+
+			double thetaRealFlex = findAngle3D(hipMarked, toeMarked, kneeMarked, 0, 0, -kneeZetaSide);
+
+
+			if(programMode == skinOnlyMarkers) {
+				printOnScreen(output, font, CV_RGB(0,0,0), 
+						upLegMarkedDist + downLegMarkedDist, 
+						relError(upLegMarkedDistMax + downLegMarkedDistMax, upLegMarkedDist + downLegMarkedDist),
+						framesCount, threshold, thetaMarked, minThetaMarked);
+				cvShowImage("toClick", frame_copy);
+				cvShowImage("skinOutput",output);
+			}
 
-			//print holes angle detection data
-			sprintf(label, "threshold: %d", threshold);
-			cvPutText(frame_copy, label, cvPoint(10,frame->height-60),&font,CV_RGB(255,255,255));
-			sprintf(label, "H angle: %.2f", thetaHoles);
-			cvPutText(frame_copy, label, cvPoint(10,frame->height-40),&font,CV_RGB(255,255,255));
-			sprintf(label, "min H angle: %.2f", minThetaHoles);
-			cvPutText(frame_copy, label, cvPoint(10,frame->height-20),&font,CV_RGB(255,255,255));
+			printOnScreen(frame_copy, font, CV_RGB(255,255,255), 
+					upLegMarkedDist + downLegMarkedDist, 
+					relError(upLegMarkedDistMax + downLegMarkedDistMax, upLegMarkedDist + downLegMarkedDist),
+					framesCount, threshold, thetaMarked, minThetaMarked);
+
+			printOnScreenRight(frame_copy, font, CV_RGB(255,255,255), 
+					upLegMarkedDist, downLegMarkedDist,  
+					upLegMarkedDistMax, downLegMarkedDistMax,  
+					kneeZetaSide, htKneeMarked, 
+					thetaABD, thetaRealFlex);
 
-			if(foundAngle) {
+			if(programMode == blackAndMarkers && foundAngle) {
+				/*
 				//print data
-				double thetaSup = findAngle(hipPoint, cvPoint(0,kneePoint.y), kneePoint);
-				double thetaHolesSup = findAngle(hipHolesPoint, cvPoint(0, kneeHolesPoint.y), kneeHolesPoint);
+				double thetaSup = findAngle2D(hipExpected, cvPoint(0,kneeExpected.y), kneeExpected);
+				double thetaMarkedSup = findAngle2D(hipMarked, cvPoint(0, kneeMarked.y), kneeMarked);
 
-				double thetaInf = findAngle(cvPoint(0,kneePoint.y), toePoint, kneePoint);
-				double thetaHolesInf = findAngle(cvPoint(0,kneeHolesPoint.y), toeHolesPoint, kneeHolesPoint);
+				double thetaInf = findAngle2D(cvPoint(0,kneeExpected.y), toeExpected, kneeExpected);
+				double thetaMarkedInf = findAngle2D(cvPoint(0,kneeMarked.y), toeMarked, kneeMarked);
 
-				printf("%7d %7.2f %7.2f [%7.2f %7.2f] %7.2f %7.2f %7.2f [%7.2f %7.2f] [%7.2f] [%7.2f]\n", framesCount, theta, thetaHoles, 
-						thetaHoles-theta, relError(theta, thetaHoles), 
-						getDistance(kneePoint, kneeHolesPoint), 
-						thetaSup-thetaHolesSup, thetaInf-thetaHolesInf
-						, getDistance(kneeHolesPoint, hipHolesPoint), getDistance(kneePoint, hipPoint)
-						, getDistance(kneePoint, hipPointBack)
-						, getDistance(kneePointBack, hipPointBack)
-						//, area
-				      );
-
-				avgThetaDiff += abs(thetaHoles-theta);
-				avgThetaDiffPercent += abs(relError(theta, thetaHoles));
-				avgKneeDistance += getDistance(kneePoint, kneeHolesPoint);
+				printf("%7d %7.2f %7.2f [%7.2f %7.2f] %7.2f %7.2f %7.2f [%7.2f %7.2f] [%7.2f] [%7.2f]\n", framesCount, thetaExpected, thetaMarked, 
+				thetaMarked-thetaExpected, relError(thetaExpected, thetaMarked), 
+				getDistance(kneeExpected, kneeMarked), 
+				thetaSup-thetaMarkedSup, thetaInf-thetaMarkedInf
+				, getDistance(kneeMarked, hipMarked), getDistance(kneeExpected, hipExpected)
+				, getDistance(kneeExpected, hipPointBack)
+				, getDistance(kneePointBack, hipPointBack)
+				//, area
+				);
+
+				avgThetaDiff += abs(thetaMarked-thetaExpected);
+				avgThetaDiffPercent += abs(relError(thetaExpected, thetaMarked));
+				avgKneeDistance += getDistance(kneePoint, kneeMarked);
+				*/
 				framesDetected ++;
 			}
 
-			cvShowImage("result",frame_copy);
+
+			if(programMode == blackAndMarkers || programMode == blackOnlyMarkers)
+				cvShowImage("result",frame_copy);
 
 
 			//Finds the minimum angle between Hip to Knee line and Knee to Toe line
-			if(thetaHoles == minThetaHoles) {
-				if(onlyValidationBlack) {
+			if(thetaMarked == minThetaMarked) {
+//				if(programMode == blackOnlyMarkers || programMode == skinOnlyMarkers) {
 					/*
 					 * if only process validation points, then minimum angle should be obtained 
 					 * by the validation points
 					 */
-				
+
 					cvCopy(frame_copy,result);
 					//lowestAngleFrame = hipSeq->total -1;
 					lowestAngleFrame = framesCount;
-				}
+//				}
 			}
 
 			//exit if we are going up and soon jumping.
 			//toe will be lost
-			//detected if minThetaHoles is littler than thetaHoles, when thetaHoles is big
-			if(thetaHoles > 140 && minThetaHoles +10 < thetaHoles)
+			//detected if minThetaMarked is littler than thetaMarked, when thetaMarked is big
+			if(thetaMarked > 140 && 
+					minThetaMarked +10 < thetaMarked &&
+					! jumpedFrames)
+			{
+				printf("\ntm: %f, mtm: %f, frame: %d\n", thetaMarked, minThetaMarked, framesCount);
 				shouldEnd = true;
+			}
 		}
 
 
-		/* wait key for pause
-		 * if ESC, q, Q then exit
+		/* 
+		 * 6
+		 * WAIT FOR KEYS
 		 */
 
 		int myDelay = playDelay;
+		//if(programMode != blackAndMarkers || foundAngle)
 		if(foundAngle)
 			myDelay = playDelayFoundAngle;
 
 		key = (char) cvWaitKey(myDelay);
-		if(key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
+		if(key == 27 || key == 'q') // 'ESC'
 			shouldEnd = true;
-		else if(key == 'f') // 'FORWARD'
+		else if (key == '+')  
+			threshold += thresholdInc;
+		else if (key == '-') 
+			threshold -= thresholdInc;
+		else if (key == 'f') { 
 			forward = true;
-		else if(key =='F') // 'FORWARD SUPER'
+			printf("forwarding ...\n");
+		} else if (key == 'F') { 
 			forwardSuper = true;
-		else if (key >0)
+			printf("super forwarding ...\n");
+		} else if (key == 'j' || key == 'J') {
+			//jump frames
+			printf("current frame: %d. Jump to: ", framesCount);
+			int jump;
+			scanf("%d", &jump);
+		
+			//works with opencv1.1!!
+			//now we can go back and forth
+			cvSetCaptureProperty( capture, CV_CAP_PROP_POS_FRAMES, jump-1 );
+			
+			framesCount = jump;
+
+			//when jumper is extending legs after maximal flexion, jump ends
+			//this jumped makes it didn't work, avoiding ending a jump
+			//when we have gone ('j') from a maximal flexion to the 1st frame again (extension)
+			jumpedFrames = true;
+			
+			//hlps to know when we jumped and we have to initialize hipOld, kneeOld, toOld
+			jumping = true;
+			printf("jumping ...\n");
+		}
+		else if (key == 'p')
 		{
 			//if paused, print "pause"
 			sprintf(label,"Pause");
-			cvPutText(frame_copy, label,cvPoint(frame->width -100,25),&font,cvScalar(0,0,255));
-			cvShowImage("result",frame_copy);
-
-			key = (char) cvWaitKey(0);
-			if(key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
-				shouldEnd = true;
-		}
+			if(programMode == skinOnlyMarkers) {
+				cvPutText(output, label,cvPoint(10, 25),&font,cvScalar(128,128,128));
+				cvShowImage("skinOutput",output);
+			} else {
+				cvPutText(frame_copy, label,cvPoint(10, 25),&font,cvScalar(0,0,255));
+				cvShowImage("result",frame_copy);
+			}
 
-		//cvShowImage("gray",gray);
+			bool done = false;
+			do{
+				key = (char) cvWaitKey(0);
+				if(key == 27 || key == 'q') {
+					shouldEnd = true;
+					done = true;
+				}
+				else if(key =='p') { 
+					threshold -= thresholdInc;
+					done = true;
+				}
+				else if(key =='+' || key == '-') {  
+					if(key =='+')  
+						threshold += thresholdInc;
+					else if(key =='-') 
+						threshold -= thresholdInc;
+		
+					if(programMode == skinOnlyMarkers) {
+						cvThreshold(gray, output, threshold, thresholdMax,CV_THRESH_BINARY_INV);
+						sprintf(label,"Pause");
+						cvPutText(output, label,cvPoint(10, 25),&font,cvScalar(128,128,128));
+						sprintf(label, "frame: %d", framesCount);
+						cvPutText(output, label, cvPoint(10,frame->height-40),&font,CV_RGB(0,0,0));
+						sprintf(label, "threshold: %d", threshold);
+						cvPutText(output, label, cvPoint(10,frame->height-20),&font,CV_RGB(0,0,0));
+						cvShowImage("skinOutput", output);
+					}
+					else {		
+						cvThreshold(gray,segmentedValidationHoles, threshold, thresholdMax,CV_THRESH_BINARY_INV);
+						//create the largest contour image (stored on temp)
+						cvThreshold(gray,segmented,threshold,thresholdMax,CV_THRESH_BINARY_INV);
+						maxrect = findLargestContour(segmented, output, showContour);
 
-		//cvShowImage("segmentedValidationHoles",segmentedValidationHoles);
-		double scale = 4;
-		IplImage* tempSmall = cvCreateImage( cvSize( cvRound (segmentedValidationHoles->width/scale), cvRound (segmentedValidationHoles->height/scale)), 8, 1 );
-		cvResize( segmentedValidationHoles, tempSmall, CV_INTER_LINEAR );
-		cvShowImage("holes",tempSmall);
+						updateHolesWin(segmentedValidationHoles);
+					}
+				}
 
+			} while (! done);
+		}
 
-		//cvShowImage("foundHoles",foundHoles);
-		//cvShowImage("output",output);
+		if(programMode == blackAndMarkers || programMode == blackOnlyMarkers) {
+			updateHolesWin(segmentedValidationHoles);
+		}
 
 	}
 
-	if(onlyValidationBlack) {
-		printf("*** Result ***\nMin angle: %.2f, lowest angle frame: %d\n", minThetaHoles, lowestAngleFrame);
-		cvNamedWindow("Minimum Frame",1);
-		cvShowImage("Minimum Frame", result);
-		cvWaitKey(0);
-	}
-	else if(foundAngleOneTime) {
+	/*
+	 * END OF MAIN LOOP
+	 */
+
+	if(programMode == blackAndMarkers && foundAngleOneTime) {
 
 		avgThetaDiff = (double) avgThetaDiff / framesDetected;
 		avgThetaDiffPercent = (double) avgThetaDiffPercent / framesDetected;
@@ -707,6 +909,8 @@
 
 		printf("\n[%f %f] %f\n", avgThetaDiff, avgThetaDiffPercent, avgKneeDistance);
 
+		// do this on R
+		/*
 		if(showStickThePoints || 
 				showStickTheLinesBetweenDifferentPoints ||
 				showStickTheLinesBetweenSamePoints) {
@@ -737,15 +941,25 @@
 				cvShowImage("Stick Figure", resultStick);
 			}
 		}
+		*/
+			
+		cvNamedWindow("Minimum Frame",1);
+		cvShowImage("Minimum Frame", result);
 
 		printf("Minimum Frame\n");
-		sprintf(label, "minblack minholes    diff diff(%)");
-		sprintf(label, "%8.2f %8.2f [%7.2f %7.2f]", minTheta, minThetaHoles, 
-				minThetaHoles-minTheta, relError(minTheta, minThetaHoles));
+		sprintf(label, "minblack minholes    diff diff(%%)");
+		sprintf(label, "%8.2f %8.2f [%7.2f %7.2f]", minThetaExpected, minThetaMarked, 
+				minThetaMarked-minThetaExpected, relError(minThetaExpected, minThetaMarked));
 		printf("%s\n" ,label);
 
 		cvWaitKey(0);
 	}
+	else {
+		printf("*** Result ***\nMin angle: %.2f, lowest angle frame: %d\n", minThetaMarked, lowestAngleFrame);
+		cvNamedWindow("Minimum Frame",1);
+		cvShowImage("Minimum Frame", result);
+		cvWaitKey(0);
+	}
 
 	/* show all windows*/	
 	/*
@@ -779,3 +993,58 @@
 }
 
 
+int menu() 
+{
+	/* initial menu */
+	printf( "Use: \n"
+			"\tq - quit the program\n"
+			"\tb - change mode to black long pants and marker validation\n"
+			"\tB - change mode to Black long pants (only markers)\n"
+			"\ts - change mode to Skin (short pants) (only markers)\n"
+			"\tj - Jump at selected frame\n"
+			"\ti - Init the program\n"
+	      );
+
+	int key;
+	int programMode = blackAndMarkers;
+	char option;
+
+	bool menuDone = false;
+	do{
+		printf("Current options:\n");
+		if(programMode == blackAndMarkers)
+			printf("\t- Black long pants and marker validation\n");
+		else if(programMode == blackOnlyMarkers)
+			printf("\t- Black long pants (only markers)\n");
+		else
+			printf("\t- Skin (short pants) (only markers)\n");
+		printf("\t- start at frame: %d\n", startAt);
+
+		scanf("%c", &option);
+		switch( option ) {
+			case 'q':
+				printf("Exiting ...\n");
+				menuDone = true;
+			case 'b':
+				programMode = blackAndMarkers;
+				break;
+			case 'B':
+				programMode = blackOnlyMarkers;
+				break;
+			case 's':
+				programMode = skinOnlyMarkers;
+				break;
+			case 'j':
+				printf("Jump at frame: ");
+				scanf("%d", &startAt);
+				break;
+			case 'i':
+				printf("Starting...\n");
+				menuDone = true;
+				break;
+		}
+	} while (! menuDone);
+
+	return programMode;
+}
+				

Modified: trunk/src/angle/kneeAngleFunctions.cpp
==============================================================================
--- trunk/src/angle/kneeAngleFunctions.cpp	(original)
+++ trunk/src/angle/kneeAngleFunctions.cpp	Mon Nov  3 17:24:17 2008
@@ -354,7 +354,8 @@
 			if(srcdataptrC[x] > 0)
 			{
 				if(srcdataptrH[x] == 0) {
-					pt.x =x;pt.y=y;
+					pt.x=x;
+					pt.y=y;
 					//cvCircle(foundHoles,pt,1, CV_RGB(128,128,128),1,8,0);
 
 					cvSeqPush( seqPoints, &pt );
@@ -554,6 +555,251 @@
 	return seqHolesEnd;
 }
 
+/*
+ * this function is realy similiar to findHoles
+ * try to do only a function
+ */
+CvSeq* findHolesSkin(IplImage *imgThresh, IplImage *imgColor, CvPoint hipOld, CvPoint kneeOld, CvPoint toeOld)
+{
+	CvPoint pt;
+	pt.x =0;pt.y=0;
+	
+	CvMat *srcmat,src_stub;
+	srcmat = cvGetMat(imgThresh, &src_stub);
+	uchar *srcdata = srcmat->data.ptr;
+	
+	int width = imgThresh->width;
+	int minx = imgThresh->width;
+	int endy = imgThresh->height;
+	
+	//stick storage
+	CvMemStorage* storage = cvCreateMemStorage(0);
+
+	CvSeq* seqPoints = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seqGroups = cvCreateSeq( 0, sizeof(CvSeq), sizeof(0), storage );
+
+//exit(0); //desp
+	//put all hole points on seqAllHoles
+	for(int y=0;y<endy;y++)
+	{
+		uchar *srcdataptr = srcdata + y*imgThresh->width;
+		for(int x=0;x<width;x++)
+		{
+			if(srcdataptr[x] == 0)
+			{
+				pt.x=x; 
+				pt.y=y;
+				//cvCircle(foundHoles,pt,1, CV_RGB(128,128,128),1,8,0);
+				cvSeqPush( seqPoints, &pt );
+			}
+		}
+	}
+
+	//assign each point to a group (a hole)
+	for( int i = 0; i < seqPoints->total; i++ ) {
+		CvPoint pt = *CV_GET_SEQ_ELEM( CvPoint, seqPoints, i ); 
+		int group = getGroup(i, pt, seqPoints,seqGroups);
+		cvSeqPush( seqGroups, &group );
+	}
+	
+
+	CvPoint pt1; CvPoint pt2; CvPoint pt3;
+ 	
+	CvSeq* seqHolesUpLeft = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seqHolesDownRight = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seqHolesCenter = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seqHolesSize = cvCreateSeq( 0, sizeof(CvSeq), sizeof(0), storage );
+	
+
+
+	for( int i = 0; i <= getMaxValue(seqGroups); i++ ) {
+		int maxX = -1;
+		int minX = 10000;
+		int maxY = -1;
+		int minY = 10000;
+		int pointsInGroup = 0;
+		for( int j = 0; j < seqGroups->total; j++ ) {
+			int group = *CV_GET_SEQ_ELEM( int, seqGroups, j ); 
+			if(group==i) {
+				CvPoint pt = *CV_GET_SEQ_ELEM( CvPoint, seqPoints, j ); 
+				if(pt.x > maxX)
+					maxX = pt.x;
+				if(pt.x < minX)
+					minX = pt.x;
+				if(pt.y > maxY)
+					maxY = pt.y;
+				if(pt.y < minY)
+					minY = pt.y;
+				pointsInGroup++;
+			}
+		}
+		if(maxX != -1) { //ripoff empty groups (appear when there are fusions between groups)
+			pt1.x = minX;
+			pt1.y = minY;
+			pt2.x = maxX;
+			pt2.y = maxY;
+			pt3 = findCenter(pt1, pt2);
+			cvSeqPush( seqHolesUpLeft, &pt1 );
+			cvSeqPush( seqHolesDownRight, &pt2 );
+			cvSeqPush( seqHolesCenter, &pt3);
+			cvSeqPush( seqHolesSize, &pointsInGroup );
+			//printf("%d(%d,%d)-(%d,%d)-(%d,%d): %d\n", i, pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y, pointsInGroup);
+		}
+	}
+	
+	CvSeq* seqIsValidSize = cvCreateSeq( 0, sizeof(CvSeq), sizeof(0), storage ); //'1' if is valid
+
+	int minSide = 6;
+	int maxSize = 200;
+	int validValue = 1;
+	int nonValidValue = 0;
+	for( int i = 0; i < seqHolesUpLeft->total; i++ ) {
+		CvPoint sp1 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesUpLeft, i ); 
+		CvPoint sp2 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesDownRight, i ); 
+		int size = *CV_GET_SEQ_ELEM( int, seqHolesSize, i ); 
+				
+		if(
+				size >= minSide && //size is higher than minSide (obvious)
+				size <= maxSize	&& //size is lowerr than maxSize (obvious)
+		//		sp2.x-sp1.x > minSide && sp2.y-sp1.y > minSide && //every side is bigger or equal to minSide
+				! (sp2.x-sp1.x > 3*(sp2.y-sp1.y)) && ! (3*(sp2.x-sp1.x) < (sp2.y-sp1.y)) //a side is not 3 times bigger than other (helps to delete shoes if appear)
+		  ) {
+			cvSeqPush( seqIsValidSize, &validValue);
+		} else {
+			cvSeqPush( seqIsValidSize, &nonValidValue );
+		}
+	}
+
+	int sizeBig1 = 0;
+	int sizeBig2 = 0;
+	int sizeBig3 = 0;
+	for( int i = 0; i < seqHolesSize->total; i++ ) {
+		int validSize = *CV_GET_SEQ_ELEM( int, seqIsValidSize, i ); 
+		int size = *CV_GET_SEQ_ELEM( int, seqHolesSize, i ); 
+		if (validSize == 1) {
+			if(size > sizeBig1) {
+				sizeBig3 = sizeBig2;
+				sizeBig2 = sizeBig1;
+				sizeBig1 = size;
+			} else if (size > sizeBig2) {
+				sizeBig3 = sizeBig2;
+				sizeBig2 = size;
+			} else if (size > sizeBig3) {
+				sizeBig3 = size;
+			}
+		}
+	}
+	
+	CvPoint hipPoint;
+	CvPoint kneePoint;
+	CvPoint toePoint;
+	hipPoint.x=0; kneePoint.x=0; toePoint.x=0;
+
+	for( int i = 0; i < seqHolesSize->total; i++ ) 
+	{
+		int validSize = *CV_GET_SEQ_ELEM( int, seqIsValidSize, i ); 
+		int size = *CV_GET_SEQ_ELEM( int, seqHolesSize, i ); 
+		CvPoint sp1 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesUpLeft, i ); 
+		CvPoint sp2 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesDownRight, i ); 
+
+		bool validSure = false;
+		CvPoint center; 
+
+		CvScalar color = CV_RGB(128, 128, 128 ); //paint rectangles in not-valid (or not big) holes.
+
+		//if size is valid
+		if (validSize) {
+			center = *CV_GET_SEQ_ELEM( CvPoint, seqHolesCenter, i ); 
+			//if never found a point before, and this are the biggest points found
+			if(pointIsNull(hipOld) && pointIsNull(kneeOld) && pointIsNull(toeOld)) {
+				if(size == sizeBig1 || size == sizeBig2 || size == sizeBig3) {
+					validSure = true;
+
+					if(hipPoint.x == 0) {
+						hipPoint.x = center.x; 
+						hipPoint.y = center.y;
+					color = CV_RGB(255, 0, 0 );
+
+					} else if(kneePoint.x == 0) {
+						kneePoint.x = center.x; 
+						kneePoint.y = center.y;
+						color = CV_RGB(0, 255, 0 );
+
+					} else {
+						toePoint.x = center.x; 
+						toePoint.y = center.y;
+						color = CV_RGB(0, 0, 255 );
+
+					}
+				}
+			}
+			//if found a point before, and this point is inside before point (ok at 300 fps)
+			//a point is also ok, if we come from a user forward (then, there's not need to be inside old point)
+			else {
+				validSure = true;
+				if(pointInside(hipOld, sp1, sp2)) {
+					hipPoint.x = center.x; 
+					hipPoint.y = center.y;
+					color = CV_RGB(255, 0, 0 );
+
+				} else if(pointInside(kneeOld, sp1,sp2)) {
+					kneePoint.x = center.x; 
+					kneePoint.y = center.y;
+					color = CV_RGB(0, 255, 0 );
+
+				} else if(pointInside(toeOld, sp1,sp2)) {
+					toePoint.x = center.x; 
+					toePoint.y = center.y;
+					color = CV_RGB(0, 0, 255);
+
+				}else 
+					validSure = false;
+			}
+		}
+
+		cvRectangle(imgThresh, 
+				cvPoint(sp1.x-1,sp1.y-1),
+				cvPoint(sp2.x+1, sp2.y+1),
+				color,1,1);
+		cvRectangle(imgColor, 
+				cvPoint(sp1.x-1,sp1.y-1),
+				cvPoint(sp2.x+1, sp2.y+1),
+				color,1,1);
+	}
+
+	if(kneePoint.x > 0) {
+		if(hipPoint.x > 0) {
+			cvLine(imgThresh,hipPoint,kneePoint,CV_RGB(0,255,0),1,1);
+			cvLine(imgColor,hipPoint,kneePoint,CV_RGB(0,255,0),1,1);
+		} if(toePoint.x > 0) {
+			cvLine(imgThresh,toePoint,kneePoint,CV_RGB(0,255,0),1,1);
+			cvLine(imgColor,toePoint,kneePoint,CV_RGB(0,255,0),1,1);
+		}
+	}
+
+	CvPoint notFoundPoint;
+	notFoundPoint.x = 0; notFoundPoint.y = 0;
+
+	CvSeq* seqHolesEnd = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+
+	if(hipPoint.x > 0) 
+		cvSeqPush( seqHolesEnd, &hipPoint );
+	else
+		cvSeqPush( seqHolesEnd, &notFoundPoint );
+
+	if(kneePoint.x > 0) 
+		cvSeqPush( seqHolesEnd, &kneePoint );
+	else
+		cvSeqPush( seqHolesEnd, &notFoundPoint );
+
+	if(toePoint.x > 0) 
+		cvSeqPush( seqHolesEnd, &toePoint );
+	else
+		cvSeqPush( seqHolesEnd, &notFoundPoint );
+
+	return seqHolesEnd;
+}
+
 
 /*
  * takes input argument as the gray form of input frame and a temp image
@@ -864,26 +1110,179 @@
 		return (int) 100 * countBlack/(countWhite + countBlack);
 }
 
-CvPoint hipSkin;
-CvPoint kneeSkin;
-CvPoint toeSkin;
+int calculateThresholdStart(IplImage * gray)
+{
+	int brightness = calculateBrightness(gray);
+	printf("brightness: %d\n", brightness);
+
+	//created image like the contour but with holes and more (stores on segmentedValidationHoles)
+	//recommended 25,255
+	//high threshold (40-60) detects more black things (useful to not confuse a hole when is close to the border)
+	//low threshold (5-10) detects less black things
+	//if the image is bright, a hight threshold is perfect to nice detect the shapes without detecting shadows
+	//int threshold = 35;
+	//put threshold min depending on brightnesss
+	//eg: nora: brightness 85 -> threshold 30
+	//eg: 44_lluis_puerta_salt6_m.MOV: brightness 73 -> threshold 10
+
+	//adjust better, because:
+	//12_carles_tejedor_salt3_m.MOV
+	//is bright:0, but if put thresh to 1 then detects bad. and to 10 is ok
+	//
+	//on the other side, 2_roger_miralles_salt3_m.MOV
+	//is really dark and it needs a thresh of 1 to work
+	//
+	//also it could be nice to have a thresh that detects three objects
+	//another option, could be to have the thresh 10 as really minimum and darker images are unsupported!
+	int thresholdStart;
+	int briMax = 85;
+	int briMin = 65;
+	//int briZero = 50;
+	int thresMax = 30;
+	int thresMin = 10;
+
+	if(brightness >= briMax) 
+		thresholdStart = thresMax;
+	//else if(brightness <= briZero)
+	//	thresholdStart = 10;
+	else if(brightness <= briMin)
+		thresholdStart = thresMin;
+	else
+		thresholdStart = brightness - briMin + thresMin;
+
+	return thresholdStart;
+}
+
+double zoomScale = 2;
+
+IplImage * zoomImage(IplImage *img) {
+	IplImage* imgZoom = cvCreateImage( cvSize( cvRound (img->width*zoomScale), 
+				cvRound (img->height*zoomScale)), 8, 3 );
+	cvResize( img, imgZoom, CV_INTER_LINEAR );
+	return imgZoom;
+}
+
+CvPoint hipMouse;
+CvPoint kneeMouse;
+CvPoint toeMouse;
+
+bool forceMouseHip = false;
+bool forceMouseKnee = false;
+bool forceMouseToe = false;
+
+bool zoomed = false;
+
+bool mouseCanMark = false;
 
 void on_mouse( int event, int x, int y, int flags, void* param )
 {
-	switch( event )
-	{
+	if(! mouseCanMark)
+		return;
+
+	if(zoomed) {
+		x = x / zoomScale;
+		y = y / zoomScale;
+	}
+
+	switch( event ) {
 		case CV_EVENT_LBUTTONDOWN:
 			{
-				if(hipSkin.x == 0)
-					hipSkin = cvPoint(x,y);
-				else if(kneeSkin.x == 0)
-					kneeSkin = cvPoint(x,y);
+				if(forceMouseHip) 
+				{
+					hipMouse = cvPoint(x,y);
+					forceMouseHip = false;
+					printf("H x:%d, y:%d\n", x, y);
+				} 
+				else if(forceMouseKnee) 
+				{
+					kneeMouse = cvPoint(x,y);
+					forceMouseKnee = false;
+					printf("K x:%d, y:%d\n", x, y);
+				} 
+				else if(forceMouseToe) 
+				{
+					toeMouse = cvPoint(x,y);
+					forceMouseToe = false;
+					printf("T x:%d, y:%d\n", x, y);
+				} 
+				else if(hipMouse.x == 0)
+				{
+					hipMouse = cvPoint(x,y);
+					printf("H x:%d, y:%d\n", x, y);
+				}
+				else if(kneeMouse.x == 0)
+				{
+					kneeMouse = cvPoint(x,y);
+					printf("K x:%d, y:%d\n", x, y);
+				}
 				else 
-					toeSkin = cvPoint(x,y);
-				//printf("x:%d, y:%d\n", x, y);
-				//
+				{
+					toeMouse = cvPoint(x,y);
+					printf("T x:%d, y:%d\n", x, y);
+				}
 			}
 			break;
 	}
 }
 
+void updateHolesWin(IplImage *segmentedValidationHoles) {
+	double scale = 4;
+	IplImage* tempSmall = cvCreateImage( cvSize( cvRound (segmentedValidationHoles->width/scale), 
+				cvRound (segmentedValidationHoles->height/scale)), 8, 1 );
+	cvResize( segmentedValidationHoles, tempSmall, CV_INTER_LINEAR );
+	cvShowImage("holes",tempSmall);
+}
+
+void printOnScreen(IplImage * img, CvFont font, CvScalar color, int legMarkedDist, double legError, int framesCount, 
+		int threshold, double thetaMarked, double minThetaMarked)
+{
+	char *label = new char[150];
+	int width = img->width;
+	int height = img->height;
+				
+	sprintf(label, "legSize: %d(%.1f%%)", legMarkedDist, legError);
+	cvPutText(img, label, cvPoint(10, height-100),&font,color);
+
+	sprintf(label, "M angle obs: %.2fÂ", thetaMarked);
+	cvPutText(img, label, cvPoint(10,height-80),&font,color);
+	
+	sprintf(label, "min M angle obs: %.2fÂ", minThetaMarked);
+	cvPutText(img, label, cvPoint(10,height-60),&font,color);
+	
+	sprintf(label, "frame: %d", framesCount);
+	cvPutText(img, label, cvPoint(10,height-40),&font,color);
+
+	sprintf(label, "threshold: %d", threshold);
+	cvPutText(img, label, cvPoint(10,height-20),&font,color);
+	
+}
+			
+void printOnScreenRight(IplImage * img, CvFont font, CvScalar color, 
+					double upLegMarkedDist, double downLegMarkedDist,  
+					double upLegMarkedDistMax, double downLegMarkedDistMax,  
+					double kneeZetaSide, double htKneeMarked, 
+					double thetaABD, double thetaRealFlex)
+{
+	char *label = new char[150];
+	int width = img->width;
+	int height = img->height;
+				
+	sprintf(label, "legUp/Down: %.1f/%.1f", upLegMarkedDist, downLegMarkedDist);
+	cvPutText(img, label, cvPoint(width-200, height-120),&font,color);
+
+	sprintf(label, "legMaxUp/Down: %.1f/%.1f", upLegMarkedDistMax, downLegMarkedDistMax);
+	cvPutText(img, label, cvPoint(width-200, height-100),&font,color);
+
+	sprintf(label, "kneeZetaSide: %.1f", kneeZetaSide);
+	cvPutText(img, label, cvPoint(width-200, height-80),&font,color);
+
+	sprintf(label, "htKneeMarked: %.2f", htKneeMarked);
+	cvPutText(img, label, cvPoint(width-200, height-40),&font,color);
+
+	sprintf(label, "sideMove: %.2fÂ", thetaABD);
+	cvPutText(img, label, cvPoint(width-200, height-60),&font,color);
+
+	sprintf(label, "real Flex: %.2fÂ", thetaRealFlex);
+	cvPutText(img, label, cvPoint(width-200, height-20),&font,color);
+}
+

Modified: trunk/src/angle/kneeAngleUtil.cpp
==============================================================================
--- trunk/src/angle/kneeAngleUtil.cpp	(original)
+++ trunk/src/angle/kneeAngleUtil.cpp	Mon Nov  3 17:24:17 2008
@@ -172,7 +172,12 @@
 
 double getDistance(CvPoint p1, CvPoint p2)
 {
-	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
+	return sqrt( pow(p1.x-p2.x, 2) + pow(p1.y-p2.y, 2) );
+}
+
+double getDistance3D(CvPoint p1, CvPoint p2, int p1z, int p2z)
+{
+	return sqrt( pow(p1.x-p2.x, 2) + pow(p1.y-p2.y, 2) + pow(p1z-p2z, 2) );
 }
 
 int checkItsOk(int val, int min, int max)
@@ -230,18 +235,32 @@
 	return false;
 }
 
-double findAngle(CvPoint p1, CvPoint p2, CvPoint pc) //pc is center point
+double findAngle2D(CvPoint p1, CvPoint p2, CvPoint pa) //pa is the point at the angle
 {
 	CvPoint d1, d2;
-	d1.x = p1.x - pc.x;
-	d1.y = p1.y - pc.y;
-	d2.x = p2.x - pc.x;
-	d2.y = p2.y - pc.y;
-	double dist1 = getDistance(p1, pc);
-	double dist2 = getDistance(p2, pc);
+	d1.x = p1.x - pa.x;
+	d1.y = p1.y - pa.y;
+	d2.x = p2.x - pa.x;
+	d2.y = p2.y - pa.y;
+	double dist1 = getDistance(p1, pa);
+	double dist2 = getDistance(p2, pa);
 	return (180.0/M_PI)*acos(((d1.x*d2.x + d1.y*d2.y))/(double)(dist1*dist2));
 }
 
+double findAngle3D(CvPoint p1, CvPoint p2, CvPoint pa, int p1z, int p2z, int paz) //pa is the point at the angle
+{
+	CvPoint d1, d2;
+	d1.x = p1.x - pa.x;
+	d1.y = p1.y - pa.y;
+	int d1z = p1z - paz;
+	d2.x = p2.x - pa.x;
+	d2.y = p2.y - pa.y;
+	int d2z = p2z - paz;
+	double dist1 = getDistance3D(p1, pa, p1z, paz);
+	double dist2 = getDistance3D(p2, pa, p2z, paz);
+	return (180.0/M_PI)*acos(((d1.x*d2.x + d1.y*d2.y + d1z*d2z))/(double)(dist1*dist2));
+}
+
 double relError(double val1, double val2)
 {
 	if(val2-val1 == 0 || val2 == 0)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]