chronojump r417 - trunk/src/angle



Author: xaviblas
Date: Fri Oct  3 21:13:18 2008
New Revision: 417
URL: http://svn.gnome.org/viewvc/chronojump?rev=417&view=rev

Log:
validation holes, and lots of improvements and fixes. also separated on three files


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

Modified: trunk/src/angle/kneeAngle.cpp
==============================================================================
--- trunk/src/angle/kneeAngle.cpp	(original)
+++ trunk/src/angle/kneeAngle.cpp	Fri Oct  3 21:13:18 2008
@@ -23,7 +23,7 @@
  * Xavier de Blas 
  * xaviblas gmail com
  *
- * version: 1.2 (Set, 3, 2008)
+ * version: 1.3 (Oct, 3, 2008)
  *
  */
 
@@ -112,6 +112,10 @@
 #include<fstream>
 #include<vector>
 #include <string>
+
+#include "kneeAngleUtil.cpp"
+#include "kneeAngleFunctions.cpp"
+
 using namespace std;
 
 //config variables
@@ -120,10 +124,15 @@
 int playDelay = 5; //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. 
+//int playDelayFoundAngle = 150; //as above, but used when angle is found. 
+int playDelayFoundAngle = 50; //as above, but used when angle is found. 
 				//Useful to see better the detected angle when something is detected
 				//recommended values: 50 - 200
 
+//used for validating
+enum { markerColorBlue = 0, markerColorRed = 1, markerColorGreen = 2, markerColorYellow = 3 };
+
+
 /* recommended: 
    showAtLinesPoints = true
    ...DiffPoints = true
@@ -139,423 +148,9 @@
 bool mixStickWithMinAngleWindow = true;
 
 
-/*
- * takes as input arguement the bounding rectangle of the largest contour and the image containing the bounding rectangle
- * Calculates the hip point
- * Hip point is the x coordinate of the white pixel having minimum x coordinate in the above bounding rectangle
- * Returns the coordinate of the hip point
- */
-CvPoint FindHipPoint(IplImage* img,CvRect roirect)
-{
-	CvPoint pt;
-	pt.x =0;pt.y=0;
-	int starty = roirect.y;
-	int endy = starty + roirect.height*2/3; /* meu: why 2/3 */
-	CvMat *srcmat,src_stub;
-	srcmat = cvGetMat(img,&src_stub);
-	uchar *srcdata = srcmat->data.ptr;
-	int width = img->width;
-	int minx = img->width;
-	int miny = img->height;
-
-	for(int y=starty;y<endy;y++)
-	{
-		uchar *srcdataptr = srcdata + y*img->width;
-		for(int x=0;x<width;x++)
-		{
-			if(srcdataptr[x] > 0)
-			{
-				if(x<minx)
-				{
-					minx = x;
-					miny = y;
-				}
-				break;
-			}
-
-		}
-	}
-	pt.x = minx;
-	pt.y = miny;
-
-	return pt;
-}
-
-/*
- * takes as input arguement the bounding rectangle of the largest contour,the image containing the bounding rectangle and the y coordinate of the hip point
- * Calculates the knee point
- * Knee point is a white pixel below the hip point and having maximum x coordinate in the bounding box
- * Returns the coordinate of the knee point
- */
-CvPoint FindKneePoint(IplImage *img,CvRect roirect,int starty)
-{
-	CvPoint pt;
-	pt.x = 0; pt.y = 0;
-	
-	//int endy = roirect.y+roirect.height*9/10; //this is ok if shoes or platform is shown in standup image
-	int endy = roirect.y+roirect.height;
-
-	CvMat *srcmat,src_stub;
-	srcmat = cvGetMat(img,&src_stub);
-	uchar *srcdata = srcmat->data.ptr;
-	int width = img->width;
-	int maxx = 0;
-	int maxy = 0;
-	for(int y=starty;y<endy;y++)
-	{
-		uchar *srcdataptr = srcdata + y*img->width;
-		for(int x= width;x>0;x--)
-		{
-			if(srcdataptr[x] > 0)
-			{
-				if(x>maxx)
-				{
-					maxx = x;
-					maxy = y;
-				}
-				break;
-			}
-		}
-	}
-	pt.x = maxx;
-	pt.y = maxy;
-
-	return pt;
-}
-
-/*
- * takes as input arguement the bounding rectangle of the largest contour,the image containing the bounding rectangle and the x and y coordinate of the knee point
- * Calculates the toe point
- * Toe point is a white pixel below the knee point and having minimum x coordinate
- * Returns the coordinate of the hip point
- */
-CvPoint FindToePoint(IplImage *img,CvRect roirect,int startx,int starty)
-{
-	CvPoint pt;
-	pt.x = 0; pt.y = 0;
-	
-	
-	/* if foot is in the image, is better to try to avoid it capturing above, if not then capture all
-	 * maybe force user to capture without foot, or ask and put a boolean
-	 */
-
-	//int endy = roirect.y+roirect.height*9/10; //this is ok if shoes or platform is shown in standup image
-	int endy = roirect.y+roirect.height;
-	
-
-	CvMat *srcmat,src_stub;
-	srcmat = cvGetMat(img,&src_stub);
-	uchar *srcdata = srcmat->data.ptr;
-	int width = img->width;
-	int minx = img->width;
-	int miny = img->height;
-	for(int y=starty;y<endy;y++)
-	{
-		uchar *srcdataptr = srcdata + y*img->width;
-		for(int x=width;x>0;x--)
-		{
-			if(srcdataptr[x] > 0)
-			{
-				if(x>startx)
-					break;
-				if(x<minx)
-				{
-					minx = x;
-					miny = y;
-				}
-				break;
-			}
-
-		}
-	}
-	pt.x = minx;
-	pt.y = miny;
-	return pt;
-}
-
-/*
- * takes input argument as the gray form of input frame and a temp image
- * Returns the bounding rectangle of the contour having maximum height
- * Draws the bounding rectangle of the largest contour on temp
- */
-
-CvRect findLargestContour(IplImage* img,IplImage* temp)
-{
-	CvContourScanner scanner;
-	CvSeq *src_contour;
-	IplImage *tempcopy = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
-	cvCopy(img,tempcopy);
-	CvMemStorage* storage = cvCreateMemStorage(0);
-	scanner = cvStartFindContours(img,storage,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
-	cvZero(temp);
-	CvRect maxrect;
-	maxrect.x=0;maxrect.y=0;maxrect.width=0;maxrect.height=0;
-	while((src_contour = cvFindNextContour(scanner))!= 0)
-	{
-		CvRect rect = ((CvContour*)src_contour)->rect;
-		if((rect.height) < (img->height)/3)
-			continue;
-		if(rect.height > maxrect.height)
-		{
-			maxrect.x = rect.x;
-			maxrect.y =	rect.y;
-			maxrect.width = rect.width;
-			maxrect.height = rect.height;
-		}
-		cvDrawContours(temp,src_contour,cvScalarAll(255),cvScalarAll(255),0,-1);
-	}
-
-	//show temp image (contour) little
-	if(showContour) {
-		cvNamedWindow("temp",1);
-		cvResize(temp, temp, CV_INTER_LINEAR);
-
-		double scale = 4;
-		IplImage* tempSmall = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 );
-		cvResize( temp, tempSmall, CV_INTER_LINEAR );
-
-		cvShowImage("temp", tempSmall);
-	}
-	
-	cvReleaseMemStorage(&storage);
-	cvReleaseImage(&tempcopy);
-	return maxrect;
-}
-
-CvPoint FixHipPoint1(IplImage* img, CvPoint hip, CvPoint knee)
-{
-	CvPoint ptHK;
-	ptHK.x =0;ptHK.y=0;
-	CvMat *srcmat,src_stub;
-	srcmat = cvGetMat(img,&src_stub);
-	uchar *srcdata = srcmat->data.ptr;
-	int width = img->width;
-
-	//find at 3/2 of hip (surely under the hand)
-	int y=hip.y*.66 + knee.y*.33;
-
-	uchar *srcdataptr = srcdata + y*img->width;
-	int startX = 0;
-	int countX = 0;
-	bool found = false;
-	for(int x=0;x<width;x++)
-	{
-		if(srcdataptr[x] > 0)
-		{
-			if(!found) {
-				startX = x;
-				countX = x;
-				found = true;
-			}
-			countX ++;
-		}
-	}
-	ptHK.x = (startX + countX) /2;
-	ptHK.y = y;
-	
-	return ptHK;
-}
-
-CvPoint FixHipPoint2(IplImage* img, int hipFirstY, CvPoint knee, CvPoint ptHK)
-{
-			
-	/* this was hippoint in 1/3 of the leg (close to the hip but just below the hand)
-	 * now do a line from knee to this hippoint and cross this line with first hippoint and x axe
-	 * we will have the first hippoint but centered on the hip (without problems with the hand)
-	 */
-
-	CvPoint kneePrima;
-	kneePrima.x = knee.x - ptHK.x; 
-	kneePrima.y = knee.y - ptHK.y; 
-
-	/*
-	 * y = (kneePrima.y / kneePrima.x) * x + d
-	 * x = (kneePrima.x / kneePrima.y) * y - d
-	 * d = -x +(kneePrima.x / kneePrima.y) * y
-	 */
-
-	double d = -knee.x + ( (kneePrima.x / (double)kneePrima.y) * knee.y);
-
-	/*
-	 * x = (kneePrima.x / kneePrima.y) * y - d
-	 */
-	 
-	CvPoint HCenter;
-	HCenter.x =0; 
-	HCenter.y = hipFirstY;
-
-	HCenter.x = ( (kneePrima.x / (double)kneePrima.y) * HCenter.y ) - d;
-
-	if(debug) {
-		printf("hipy(%d) ",hipFirstY);
-		printf("knee(%d,%d) ",knee.x, knee.y);
-		printf("ptHK(%d,%d) ",ptHK.x, ptHK.y);
-		printf("kneePrima(%d,%d) ",kneePrima.x, kneePrima.y);
-		printf("HCenter(%d,%d) ",HCenter.x, HCenter.y);
-		printf("kneePrima x/y:%.2f ", kneePrima.x / (double)kneePrima.y);
-		printf("d:%.1f", d);
-		printf("\n");
-	}
-
-	return HCenter;
-}
-
-/* at first photogramm where knee or foot is detected (it will not be too horizontal) find it's width and use all the time to fix kneex
- * at knee is called only done one time (because in max flexion, the back is line with the knee and there will be problems knowing knee width
- * at foot is called all the time
- */
-int FindWidth(IplImage* img, CvPoint kneeOrFoot)
-{
-	CvMat *srcmat,src_stub;
-	srcmat = cvGetMat(img,&src_stub);
-	uchar *srcdata = srcmat->data.ptr;
-	int width = img->width;
-
-	int y=kneeOrFoot.y;
-
-	uchar *srcdataptr = srcdata + y*img->width;
-	int countX = 0;
-	for(int x=kneeOrFoot.x-1;srcdataptr[x];x--)
-	{
-		countX ++;
-	}
-
-	return countX;;
-}
-
-double getDistance(CvPoint p1, CvPoint p2)
-{
-	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
-}
-
-bool upperSimilarThanLower(CvPoint hipPoint, CvPoint kneePoint, CvPoint footPoint)
-{
-	double upper = getDistance(kneePoint, hipPoint); 
-	double lower = getDistance(kneePoint, footPoint);
-	double big = 0; 
-	double little = 0;
-	
-	if(upper > lower) {
-		big = upper;
-		little = lower;
-	} else {
-		big = lower;
-		little = upper;
-	}
-
-	if(debug)
-		printf("upper(%.1f), lower(%.1f), big/little (%.2f)\n",upper, lower, big/(double)little);
-
-	//if one is not n times or more bigger than the other
-	//consider that if camera hides shoes and a bit more up, 2 times is risky in a maximal flexion
-	//consider also that this data is previous to fixing
-	double n = 2.5;
-	if(big / (double)little < n)
-		return true;
-	else 
-		return false;
-}
-
-bool pointIsNull(CvPoint pt) {
-	CvPoint notFoundPoint;
-	notFoundPoint.x = 0; notFoundPoint.y = 0;
-	if(pt.x == notFoundPoint.x && pt.y == notFoundPoint.y) 
-		return true;
-	else 
-		return false;
-}
-
-/* paints stick figure at end */
-void paintStick(IplImage *img, int lowestAngleFrame, CvSeq *hipSeq, CvSeq* kneeSeq, CvSeq *footSeq, 
-		bool showPoints, bool showLinesDiff, bool showLinesSame, bool onlyStartMinEnd) {
-	
-	//colors for start, end points, and up, down lines
-	CvScalar startColor = CV_RGB(0,0,255); //start blue
-	CvScalar minAngleColor = CV_RGB(255,0,0); //min angle red
-	CvScalar endColor = CV_RGB(0,255,0); //end green
-	CvScalar connectedWithPreviousColor = CV_RGB(255,255,0); //yellow
-	CvScalar unConnectedWithPreviousColor = CV_RGB(128,128,128); //grey
-	CvScalar currentColor;
-	int size = 0;
-	
-	bool lastFound = false;
-	bool neverFound = true;
-
-	for( int i = 0; i < hipSeq->total; i++ )
-	{
-		CvPoint hip = *CV_GET_SEQ_ELEM( CvPoint, hipSeq, i );
-		CvPoint knee = *CV_GET_SEQ_ELEM( CvPoint, kneeSeq, i );
-		CvPoint foot = *CV_GET_SEQ_ELEM( CvPoint, footSeq, i );
-
-		//if this point was found
-		if(!pointIsNull(hip)) {
-
-			//colors are different depending on phase
-			if(i < lowestAngleFrame)
-				currentColor = startColor;
-			else if(i > lowestAngleFrame)
-				currentColor = endColor;
-			else
-				currentColor = minAngleColor;
-
-			//size of some points is bigger, also decide if paint angle lines
-			bool paintAngleLines = true;
-			if(neverFound || i == lowestAngleFrame || i == hipSeq->total -1 )
-				size = 3;
-			else {
-				size = 1;
-				if(onlyStartMinEnd)
-					paintAngleLines = false;
-			}
-
-			if(showPoints) {
-				cvCircle(img,knee,size, currentColor,1,8,0);
-				cvCircle(img,hip,size, currentColor,1,8,0);
-				cvCircle(img,foot,size, currentColor,1,8,0);
-			}
-			if(showLinesDiff && paintAngleLines) {
-				cvLine(img,knee,hip,currentColor,1,1);
-				cvLine(img,knee,foot,currentColor,1,1);
-			}
-			if(showLinesSame) {
-				if(i>0) {
-					CvPoint hipOld = *CV_GET_SEQ_ELEM( CvPoint, hipSeq, i-1);
-					CvPoint kneeOld = *CV_GET_SEQ_ELEM( CvPoint, kneeSeq, i-1);
-					CvPoint footOld = *CV_GET_SEQ_ELEM( CvPoint, footSeq, i-1);
-
-					//only paint line if previous point was found
-					if(!pointIsNull(hipOld)) {
-						cvLine(img, hip, hipOld, connectedWithPreviousColor,1,1);
-						cvLine(img, knee, kneeOld, connectedWithPreviousColor,1,1);
-						cvLine(img, foot, footOld, connectedWithPreviousColor,1,1);
-					}
-				}
-			}
-			lastFound = true;
-			neverFound = false;
-		} else 
-			lastFound = false;
-	}
-	
-	//print text	
-	CvFont font;
-	int fontLineType = CV_AA; // change it to 8 to see non-antialiased graphics
-	cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, .7, .7, 0.0, 1, fontLineType);
-	char *label = new char[10];
-	sprintf(label,"1st");
-	cvPutText(img, label,cvPoint(20, 20),&font,startColor);
-	sprintf(label,"Min");
-	cvPutText(img, label,cvPoint(20, 40),&font,minAngleColor);
-	sprintf(label,"Last");
-	cvPutText(img, label,cvPoint(20, 60),&font,endColor);
-}
 
 int main(int argc,char **argv)
 {
-	//TODO:
-	//add args for debug, record to file, speed, fondAngle value, ...
-	//currently this variables are global and defined at the top of the file
-	
 	if(argc < 2)
 	{
 		cout<<"Provide file location as a first argument..."<<endl;
@@ -568,23 +163,32 @@
 		exit(0);
 	}
 
-	double framesNumber = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
-	printf("--%f--", framesNumber);
+	int framesNumber = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
+	printf("--%d--\n", framesNumber);
 
 	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;
 	
 	bool foundAngle = false; //found angle on current frame
-	//bool foundLast = false; //on previous frame
 	bool foundAngleOneTime = false; //found angle at least one time on the video
 
-	double knee2Hip,knee2Foot,hip2Foot,theta;
+	double knee2Hip,knee2Foot,hip2Foot;
+	double theta, thetaHoles;
 	string text,angle;
-	double mintheta = 360;
+	double minTheta = 360;
+	double minThetaHoles = 360;
 	char buffer[15];
-	cvNamedWindow("frame",1);
+	cvNamedWindow("result",1);
+
+//	cvNamedWindow("gray",1);//meu
+	cvNamedWindow("holes",1); //meu
+//	cvNamedWindow("foundHoles",1); //meu
+//	cvNamedWindow("output",1);
 
 	int kneePointWidth = -1;
 	int footPointWidth;
@@ -598,7 +202,8 @@
 	char *label = new char[30];
 	CvFont font;
 	int fontLineType = CV_AA; // change it to 8 to see non-antialiased graphics
-	cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, .7, .7, 0.0, 1, fontLineType);
+	double fontSize = .4;
+	cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, fontSize, fontSize, 0.0, 1, fontLineType);
 	
 	char key;
 	bool shouldEnd = false;
@@ -610,7 +215,6 @@
 	CvSeq* footSeq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), stickStorage );
 
 
-	//for(;;)
 	while(!shouldEnd) 
 	{
 
@@ -628,6 +232,9 @@
 		{
 			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);
@@ -637,8 +244,23 @@
 
 		cvSmooth(frame_copy,frame_copy,2,5,5);
 		cvCvtColor(frame_copy,gray,CV_BGR2GRAY);
+
+		//created image like the contour but with holes and more (stores on segmentedValidationHoles)
+		cvThreshold(gray,segmentedValidationHoles,30,255,CV_THRESH_BINARY_INV);
+
+		//create the largest contour image (stored on temp)
 		cvThreshold(gray,segmented,30,255,CV_THRESH_BINARY_INV);
-		CvRect maxrect = findLargestContour(segmented,output);
+		CvRect 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
+		CvSeq* seqHolesEnd = findHoles(output, segmentedValidationHoles, foundHoles, maxrect, frame_copy);
+		CvPoint hipHolesPoint = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 0); 
+		CvPoint kneeHolesPoint = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 1 ); 
+		CvPoint toeHolesPoint = *CV_GET_SEQ_ELEM( CvPoint, seqHolesEnd, 2 ); 
+
+
 		CvPoint hipPoint = FindHipPoint(output,maxrect);
 		CvPoint kneePoint = FindKneePoint(output,maxrect,hipPoint.y);
 		CvPoint footPoint = FindToePoint(output,maxrect,kneePoint.x,kneePoint.y);
@@ -665,54 +287,121 @@
 		{
 			cvCircle(frame_copy,kneePoint,2, CV_RGB(255,0,255),1,8,0);
 			
-			//find width of knee, only one time and will be used for all the prhotogrammes
+			//find width of knee, only one time and will be used for all the photogrammes
 			if(kneePointWidth == -1) {
 				kneePointWidth = FindWidth(output, kneePoint);
 			}
 
-			//fix kneepoint.x at the right 1/3 of the knee width
-			kneePoint.x -= kneePointWidth /3;
-			cvCircle(frame_copy,kneePoint,3, CV_RGB(255,0,0),1,8,0);
+			//fix kneepoint.x at the right 1/2 of the knee width
+			kneePoint.x -= kneePointWidth /2;
+			cvCircle(frame_copy,kneePoint,3, CV_RGB(0,255,0),1,8,0);
+
 
+			//find width of foot for each photogramme
+			footPointWidth = FindWidth(output, footPoint);
+			cvCircle(frame_copy,footPoint,2, CV_RGB(255,0,255),1,8,0);
+			
+			//fix footpoint.x at the 1/2 of the foot width
+			footPoint.x -= footPointWidth /2;
+			cvCircle(frame_copy,footPoint,3, CV_RGB(0,0,255),1,8,0);
 
+			
 			//fix hipPoint ...
 			int hipPointFirstY = hipPoint.y;
 			cvCircle(frame_copy,hipPoint,2, CV_RGB(255,0,255),1,8,0);
 			
 			//... find at 3/2 of hip (surely under the hand) ...
-			hipPoint = FixHipPoint1(output, hipPoint, kneePoint);
+			theta = findAngle(hipPoint, footPoint, kneePoint);
+			hipPoint = FixHipPoint1(output, hipPoint, kneePoint, theta);
 			cvCircle(frame_copy,hipPoint,2, CV_RGB(255,0,255),1,8,0);
 
 			//... cross first hippoint with the knee-hippoint line to find real hippoint
 			hipPoint = FixHipPoint2(output, hipPointFirstY, kneePoint, hipPoint);
 			cvCircle(frame_copy,hipPoint,3, CV_RGB(255,0,0),1,8,0);
 			
-			//find width of foot for each photogramme
-			footPointWidth = FindWidth(output, footPoint);
-			cvCircle(frame_copy,footPoint,2, CV_RGB(255,0,255),1,8,0);
-			
-			//fix footpoint.x at the 1/2 of the foot width
-			footPoint.x -= footPointWidth /2;
-			cvCircle(frame_copy,footPoint,3, CV_RGB(255,0,0),1,8,0);
 
-			//draw 2 main lines
-			knee2Foot = getDistance(kneePoint, footPoint);
-			knee2Hip = getDistance(kneePoint, hipPoint);
-			hip2Foot = getDistance(hipPoint, footPoint);
-			theta = (180.0/M_PI)*acos(((knee2Foot*knee2Foot+knee2Hip*knee2Hip)-hip2Foot*hip2Foot)/(2*knee2Foot*knee2Hip));
-			cvLine(frame_copy,kneePoint,hipPoint,CV_RGB(0,0,255),1,1);
-			cvLine(frame_copy,kneePoint,footPoint,CV_RGB(0,0,255),1,1);
+			//find flexion angle
+			theta = findAngle(hipPoint, footPoint, kneePoint);
+			thetaHoles = findAngle(hipHolesPoint, toeHolesPoint, kneeHolesPoint);
 			
+			//draw 2 main lines
+			cvLine(frame_copy,kneePoint,hipPoint,CV_RGB(128,128,128),1,1);
+			cvLine(frame_copy,kneePoint,footPoint,CV_RGB(128,128,128),1,1);
 			
 			cvSeqPush( hipSeq, &hipPoint );
 			cvSeqPush( kneeSeq, &kneePoint );
 			cvSeqPush( footSeq, &footPoint );
 
+			/*draw line of knee distance between holes validation and black detection
+			 */
+
+			if(kneeHolesPoint.x > 0) 
+				cvLine(frame_copy,kneeHolesPoint, kneePoint,CV_RGB(225,225,0),1,1);
+			if(hipHolesPoint.x > 0) 
+				cvLine(frame_copy,hipHolesPoint, hipPoint,CV_RGB(225,225,0),1,1);
+			if(toeHolesPoint.x > 0) 
+				cvLine(frame_copy,toeHolesPoint, footPoint,CV_RGB(225,225,0),1,1);
+
+			/*
+			 * draw perpendicular line (min distance)
+			 if(kneeHolesPoint.x > 0 && hipHolesPoint > 0) { 
+
+			 CvPoint hipHolesPrima;
+			 hipHolesPrima.x = hipHolesPoint.x - kneeHolesPoint.x; 
+			 hipHolesPrima.y = hipHolesPoint.y - kneeHolesPoint.y; 
+
+			 CvPoint hipPrima;
+			 hipPrima.x = hipPoint.x - kneeHolesPoint.x; 
+			 hipPrima.y = hipPoint.y - kneeHolesPoint.y; 
+
+			//find angle on knee	
+			int hip2KneeHoles = getDistance(hipPoint, kneeHolesPoint);
+			int hipHoles2KneeHoles = getDistance(hipHolesPoint, kneeHolesPoint);
+			double theta2 = (180.0/M_PI)*acos(((hipHolesPrima.x*hipPrima.x + hipHolesPrima.y*hipPrima.y))/(double)(hip2KneeHoles*hipHoles2KneeHoles));
+			int d1 = hip2KneeHoles * sin((M_PI/180.0)*theta2);
+			int d2 = hip2KneeHoles * cos((M_PI/180.0)*theta2);
+
+
+			//angle of kneeHoles-hipHoles with horizontal
+			double theta3 = (180.0/M_PI)*acos(((hipHolesPrima.x*hipHolesPrima.x + hipHolesPrima.y*0))/(double)(hipHoles2KneeHoles*hipHolesPrima.x));
+			CvPoint crossPrima;
+			crossPrima.y = hipHoles2KneeHoles * sin((M_PI/180.0)*theta3);
+			crossPrima.x = hipHoles2KneeHoles * cos((M_PI/180.0)*theta3);
+			CvPoint cross;
+			cross.y = kneeHolesPoint.y + crossPrima.y;
+			cross.x = kneeHolesPoint.x + crossPrima.x;
+			cvCircle(frame_copy,cross,3, CV_RGB(128,128,128),1,8,0);
+
+
+
+
+			sprintf(label, "a3: %f", theta3);
+			cvPutText(frame_copy, label, 
+			cvPoint((hipHolesPoint.x+hipPoint.x)/2, 40),
+			&font,cvScalar(0,0,255));
+
+			sprintf(label, "h2kh: %d, hh2kh: %d", hip2KneeHoles, hipHoles2KneeHoles);
+			cvPutText(frame_copy, label, 
+			cvPoint((hipHolesPoint.x+hipPoint.x)/2, 20),
+			&font,cvScalar(0,0,255));
+			sprintf(label, "a: %f, d1: %d, d2: %d", theta2, d1, d2);
+			cvPutText(frame_copy, label, 
+			cvPoint((hipHolesPoint.x+hipPoint.x)/2, (hipHolesPoint.y+hipPoint.y)/2),
+			&font,cvScalar(0,0,255));
+			}
+			*/
+
+
+
 
 			//Finds the minimum angle between Hip to Knee line and Knee to Toe line
-			if(theta < mintheta)
+			if(thetaHoles < minThetaHoles)
 			{
-				mintheta = theta;
+				minThetaHoles = thetaHoles;
+			}
+			if(theta < minTheta)
+			{
+				minTheta = theta;
 				cvCopy(frame_copy,result);
 				lowestAngleFrame = hipSeq->total -1;
 			}
@@ -724,17 +413,21 @@
 					CV_RGB(255,0,0),1,1);
 
 			//print angles
-			sprintf(label, "current: %.1f", theta);
-			cvPutText(frame_copy, label, cvPoint(5,frame->height /2),&font,cvScalar(0,0,255));
-			sprintf(label,     "min:     %.1f", mintheta);
-			cvPutText(frame_copy, label, cvPoint(5,frame->height /2 +30),&font,cvScalar(0,0,255));
+			sprintf(label, "        black  holes  diff diff(%)");
+			cvPutText(frame_copy, label, cvPoint(5,frame->height *.7),&font,cvScalar(0,0,255));
+			sprintf(label, "current: %.1f %.1f %.1f %.1f", theta, thetaHoles, 
+					thetaHoles-theta, relError(theta, thetaHoles));
+			cvPutText(frame_copy, label, cvPoint(5,frame->height *.7 +20),&font,cvScalar(0,0,255));
+			sprintf(label, "min:     %.1f %.1f %.1f %.1f", minTheta, minThetaHoles, 
+					minThetaHoles-minTheta, relError(minTheta, minThetaHoles));
+			cvPutText(frame_copy, label, cvPoint(5,frame->height *.7 +40),&font,cvScalar(0,0,255));
 		} else{
 			cvSeqPush( hipSeq, &notFoundPoint );
 			cvSeqPush( kneeSeq, &notFoundPoint );
 			cvSeqPush( footSeq, &notFoundPoint );
 		}
 			
-		cvShowImage("frame",frame_copy);
+		cvShowImage("result",frame_copy);
 
 		/* wait key for pause
 		 * if ESC, q, Q then exit
@@ -752,16 +445,29 @@
 			//if paused, print "pause"
 			sprintf(label,"Pause");
 			cvPutText(frame_copy, label,cvPoint(frame->width -100,25),&font,cvScalar(0,0,255));
-			cvShowImage("frame",frame_copy);
+			cvShowImage("result",frame_copy);
 
 			key = (char) cvWaitKey(0);
 			if(key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
 				shouldEnd = true;
 		}
 
-	}
+		//cvShowImage("gray",gray);
+		
+		//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);
+
 
+		//cvShowImage("foundHoles",foundHoles);
+		//cvShowImage("output",output);
+	}
+	
 	if(foundAngleOneTime) {
+
+
 		if(showStickThePoints || 
 				showStickTheLinesBetweenDifferentPoints ||
 				showStickTheLinesBetweenSamePoints) {
@@ -781,26 +487,27 @@
 			if(mixStickWithMinAngleWindow)
 				paintStick(result, lowestAngleFrame, hipSeq, kneeSeq, footSeq, 
 						showStickThePoints, showStickTheLinesBetweenDifferentPoints,
-						showStickTheLinesBetweenSamePoints, showStickOnlyStartMinEnd);
+						showStickTheLinesBetweenSamePoints, showStickOnlyStartMinEnd, font);
 			else {
 				paintStick(resultStick, lowestAngleFrame, hipSeq, kneeSeq, footSeq, 
 						showStickThePoints, showStickTheLinesBetweenDifferentPoints,
-						showStickTheLinesBetweenSamePoints, showStickOnlyStartMinEnd);
+						showStickTheLinesBetweenSamePoints, showStickOnlyStartMinEnd, font);
 				cvNamedWindow("Stick Figure",1);
 				cvShowImage("Stick Figure", resultStick);
 			}
 		}
 		
 		cvNamedWindow("Minimum Frame",1);
-		sprintf(label,"%.3f",mintheta);
-		cvPutText(result, label,cvPoint(65,40),&font,cvScalar(0,0,255));
+		sprintf(label, "        black  holes  diff diff(%)");
+		cvPutText(result, label, cvPoint(5,frame->height *.7),&font,cvScalar(0,0,255));
+		sprintf(label, "%.1f %.1f %.1f %.1f", minTheta, minThetaHoles, 
+					minThetaHoles-minTheta, relError(minTheta, minThetaHoles));
+		cvPutText(result, label, cvPoint(5,frame->height *.7 +20),&font,cvScalar(0,0,255));
 		cvShowImage("Minimum Frame", result);
 		
-		
 		cvWaitKey(0);
 	}
 
-
 	/* show all windows*/	
 	/*
 	cvNamedWindow("gray",1);
@@ -818,6 +525,7 @@
 	cvNamedWindow("output",1);
 	cvShowImage("output", output);
 	*/
+
 	
 	cvClearMemStorage( stickStorage );
 
@@ -825,6 +533,8 @@
 	cvReleaseImage(&frame_copy);
 	cvReleaseImage(&gray);
 	cvReleaseImage(&segmented);
+	cvReleaseImage(&segmentedValidationHoles);
+	cvReleaseImage(&foundHoles);
 	cvReleaseImage(&edge);
 	cvReleaseImage(&temp);
 	cvReleaseImage(&output);

Added: trunk/src/angle/kneeAngleFunctions.cpp
==============================================================================
--- (empty file)
+++ trunk/src/angle/kneeAngleFunctions.cpp	Fri Oct  3 21:13:18 2008
@@ -0,0 +1,686 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Initally coded by (v.1.0):
+ * Sharad Shankar & Onkar Nath Mishra
+ * http://www.logicbrick.com/
+ * 
+ * Updated by:
+ * Xavier de Blas 
+ * xaviblas gmail com
+ *
+ *
+ */
+
+
+
+#include "opencv/cv.h"
+#include "opencv/highgui.h"
+#include <opencv/cxcore.h>
+#include "stdio.h"
+#include "math.h"
+#include<iostream>
+#include<fstream>
+#include<vector>
+#include <string>
+
+
+
+/*
+ * takes as input arguement the bounding rectangle of the largest contour and the image containing the bounding rectangle
+ * Calculates the hip point
+ * Hip point is the x coordinate of the white pixel having minimum x coordinate in the above bounding rectangle
+ * Returns the coordinate of the hip point
+ */
+CvPoint FindHipPoint(IplImage* img,CvRect roirect)
+{
+	CvPoint pt;
+	pt.x =0;pt.y=0;
+	int starty = roirect.y;
+	int endy = starty + roirect.height*2/3; /* meu: why 2/3 */
+	CvMat *srcmat,src_stub;
+	srcmat = cvGetMat(img,&src_stub);
+	uchar *srcdata = srcmat->data.ptr;
+	int width = img->width;
+	int minx = img->width;
+	int miny = img->height;
+
+	//use to fount the lowest consecutive point (under the minx, miny)
+	//then we will found the 1/2 height between  both
+	int minx2 = img->width;
+	int miny2 = -1;
+
+	bool foundNow = false;
+	for(int y=starty;y<endy;y++)
+	{
+		uchar *srcdataptr = srcdata + y*img->width;
+		for(int x=0;x<width;x++)
+		{
+			if(srcdataptr[x] > 0)
+			{
+				if(x<minx)
+				{
+					minx = x;
+					miny = y;
+					foundNow = true;
+				}
+				else if(foundNow && x==minx) {
+					minx2 = x;
+					miny2 = y;
+				} else
+					foundNow = false;
+		
+				break;
+			}
+		}
+	}
+	
+	pt.x = minx;
+	if(miny2 != -1 && minx == minx2)
+		pt.y = (miny2+miny)/2;
+	else 
+		pt.y = miny;
+
+	return pt;
+}
+
+/*
+ * takes as input arguement the bounding rectangle of the largest contour,the image containing the bounding rectangle and the y coordinate of the hip point
+ * Calculates the knee point
+ * Knee point is a white pixel below the hip point and having maximum x coordinate in the bounding box
+ * Returns the coordinate of the knee point
+ */
+CvPoint FindKneePoint(IplImage *img,CvRect roirect,int starty)
+{
+	CvPoint pt;
+	pt.x = 0; pt.y = 0;
+	
+	//int endy = roirect.y+roirect.height*9/10; //this is ok if shoes or platform is shown in standup image
+	int endy = roirect.y+roirect.height;
+
+	CvMat *srcmat,src_stub;
+	srcmat = cvGetMat(img,&src_stub);
+	uchar *srcdata = srcmat->data.ptr;
+	int width = img->width;
+	int maxx = 0;
+	int maxy = 0;
+	
+	//use to fount the lowest consecutive point (under the maxx, maxy)
+	//then we will found the 1/2 height between  both
+	int maxx2 = 0;
+	int maxy2 = -1;
+	
+	bool foundNow = false;
+	for(int y=starty;y<endy;y++)
+	{
+		uchar *srcdataptr = srcdata + y*img->width;
+		for(int x= width;x>0;x--)
+		{
+			if(srcdataptr[x] > 0)
+			{
+				if(x>maxx)
+				{
+					maxx = x;
+					maxy = y;
+					foundNow = true;
+				}
+				else if(foundNow && x==maxx) {
+					maxx2 = x;
+					maxy2 = y;
+				} else
+					foundNow = false;
+		
+				break;
+			}
+		}
+	}
+	pt.x = maxx;
+	if(maxy2 != -1 && maxx == maxx2)
+		pt.y = (maxy2+maxy)/2;
+	else 
+		pt.y = maxy;
+
+	return pt;
+}
+
+/*
+ * takes as input arguement the bounding rectangle of the largest contour,the image containing the bounding rectangle and the x and y coordinate of the knee point
+ * Calculates the toe point
+ * Toe point is a white pixel below the knee point and having minimum x coordinate
+ * Returns the coordinate of the hip point
+ */
+CvPoint FindToePoint(IplImage *img,CvRect roirect,int startx,int starty)
+{
+	CvPoint pt;
+	pt.x = 0; pt.y = 0;
+	
+	
+	/* if foot is in the image, is better to try to avoid it capturing above, if not then capture all
+	 * maybe force user to capture without foot, or ask and put a boolean
+	 */
+
+	//int endy = roirect.y+roirect.height*9/10; //this is ok if shoes or platform is shown in standup image
+	int endy = roirect.y+roirect.height;
+	
+
+	CvMat *srcmat,src_stub;
+	srcmat = cvGetMat(img,&src_stub);
+	uchar *srcdata = srcmat->data.ptr;
+	int width = img->width;
+	int minx = img->width;
+	int miny = img->height;
+	for(int y=starty;y<endy;y++)
+	{
+		uchar *srcdataptr = srcdata + y*img->width;
+		for(int x=width;x>0;x--)
+		{
+			if(srcdataptr[x] > 0)
+			{
+				if(x>startx)
+					break;
+				if(x<minx)
+				{
+					minx = x;
+					miny = y;
+				}
+				break;
+			}
+
+		}
+	}
+	pt.x = minx;
+	pt.y = miny;
+	return pt;
+}
+
+
+/* 
+ * imgC (image Contour)
+ * imgH (image Holes)
+ */
+CvSeq* findHoles(IplImage *imgC, IplImage *imgH, IplImage *foundHoles, CvRect roirect, IplImage *imgMain)
+{
+	CvPoint pt;
+	pt.x =0;pt.y=0;
+	int starty = roirect.y;
+	int endy = starty + roirect.height;
+	
+	CvMat *srcmatC,src_stubC;
+	srcmatC = cvGetMat(imgC, &src_stubC);
+	uchar *srcdataC = srcmatC->data.ptr;
+	
+	CvMat *srcmatH,src_stubH;
+	srcmatH = cvGetMat(imgH, &src_stubH);
+	uchar *srcdataH = srcmatH->data.ptr;
+
+	int width = imgC->width;
+	int minx = imgC->width;
+	int miny = imgC->height;
+	
+	//stick storage
+	CvMemStorage* storage = cvCreateMemStorage(0);
+	CvSeq* seq0 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq1 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq2 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq3 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq4 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq5 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq6 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq7 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq8 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seq9 = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+
+	cvZero(foundHoles);
+
+	CvSeq* seqPoints = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	CvSeq* seqGroups = cvCreateSeq( 0, sizeof(CvSeq), sizeof(0), storage );
+
+	//put all hole points on seqAllHoles
+	for(int y=starty;y<endy;y++)
+	{
+		uchar *srcdataptrC = srcdataC + y*imgC->width;
+		uchar *srcdataptrH = srcdataH + y*imgH->width;
+		for(int x=0;x<width;x++)
+		{
+			if(srcdataptrC[x] > 0)
+			{
+				if(srcdataptrH[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 );
+	}
+
+	/*
+	for( int i = 0; i < seqGroups->total; i++ ) {
+		int group = *CV_GET_SEQ_ELEM( int, seqGroups, i ); 
+		CvPoint pt = *CV_GET_SEQ_ELEM( CvPoint, seqPoints, i ); 
+		printf("(%d,%d):%d ", pt.x, pt.y, group);
+	}
+
+	printf("\n");
+*/
+		//find three biggest seqs
+		/*	
+		 * seq0, seq1, ... amb els punts
+		 * seqHolesUpLeft un seq amb els 10 punts de dalt a l'esquerra de cada hole 
+		 * seqHolesDownRight un seq amb els 10 punts de baix a la dreta de cada hole
+		 * seqHolesCenter un seq amb els 10 punts centre de cada hole
+		 * seqHolesSize un seq amb les mides de cada hole (en nombre de punts)
+		 * que miri la 3a mes gran a seqHolesize (sempre i quan la seva horiz i vertical sigui d'uns valors minims (per no agafar linies rectes llargues)), fer-ho restant el downRight dels upleft per ax i y
+		 * que assigni hip al seqHolesCenter que aparegui en primera posicià dels 3 que sÃn prou grans
+		 * que assigni knee al seqHolesCenter que aparegui en segona posicià dels 3 que sÃn prou grans
+		 * que assigni toe al seqHolesCenter que aparegui en tercera posicià dels 3 que sÃn prou grans
+		 * que pinti un cercle a cada un dels tres punts i faci l'angle...
+		 *
+		 * finalment, agafar la imatge gray (la del histograma i pintar de negre tots els punts que estiguin blancs dels seq0..seq1.. triats com a hip, knee, toe)
+		 * -----------------------
+		 *
+		 */
+
+	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* seqIsValid = cvCreateSeq( 0, sizeof(CvSeq), sizeof(0), storage ); //'1' if is valid
+
+	int minSide = 6;
+	int maxSize = 10000;
+	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( seqIsValid, &validValue);
+		} else {
+			cvSeqPush( seqIsValid, &nonValidValue );
+		}
+	}
+
+	int sizeBig1 = 0;
+	int sizeBig2 = 0;
+	int sizeBig3 = 0;
+	for( int i = 0; i < seqHolesSize->total; i++ ) {
+		int valid = *CV_GET_SEQ_ELEM( int, seqIsValid, i ); 
+		int size = *CV_GET_SEQ_ELEM( int, seqHolesSize, i ); 
+		if (valid==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 valid = *CV_GET_SEQ_ELEM( int, seqIsValid, i ); 
+		int size = *CV_GET_SEQ_ELEM( int, seqHolesSize, i ); 
+		if (valid && (size == sizeBig1 || size == sizeBig2 || size == sizeBig3)) {
+			CvPoint sp1 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesUpLeft, i ); 
+			CvPoint sp2 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesDownRight, i ); 
+			CvPoint center = *CV_GET_SEQ_ELEM( CvPoint, seqHolesCenter, i ); 
+			if(hipPoint.x == 0) {
+				cvRectangle(imgMain, 
+						cvPoint(sp1.x-1,sp1.y-1),
+						cvPoint(sp2.x+1, sp2.y+1),
+						CV_RGB(255,0,0),1,1);
+				hipPoint.x = center.x; hipPoint.y = center.y;
+				cvCircle(imgMain,center,1, CV_RGB(255,255,0),CV_FILLED,8,0);
+			} else if(kneePoint.x == 0) {
+				cvRectangle(imgMain, 
+						cvPoint(sp1.x-1,sp1.y-1),
+						cvPoint(sp2.x+1, sp2.y+1),
+						CV_RGB(0,255,0),1,1);
+				kneePoint.x = center.x; kneePoint.y = center.y;
+				cvCircle(imgMain,center,1, CV_RGB(255,255,0),CV_FILLED,8,0);
+			} else {
+				cvRectangle(imgMain, 
+						cvPoint(sp1.x-1,sp1.y-1),
+						cvPoint(sp2.x+1, sp2.y+1),
+						CV_RGB(0,0,255),1,1);
+				toePoint.x = center.x; toePoint.y = center.y;
+				cvCircle(imgMain,center,1, CV_RGB(255,255,0),CV_FILLED,8,0);
+			}
+		}
+	}
+
+	if(kneePoint.x > 0) {
+		if(hipPoint.x > 0)
+			cvLine(imgMain,hipPoint,kneePoint,CV_RGB(128,128,128),1,1);
+		if(toePoint.x > 0)
+			cvLine(imgMain,toePoint,kneePoint,CV_RGB(128,128,128),1,1);
+	}
+	
+	/* Test:
+	 * paint rectangles in all detected holes.
+	 */
+/*
+	for( int i = 0; i < seqHolesSize->total; i++ ) {
+			CvPoint sp1 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesUpLeft, i ); 
+			CvPoint sp2 = *CV_GET_SEQ_ELEM( CvPoint, seqHolesDownRight, i ); 
+			int radious = (sp2.y - sp1.y) /2;
+			if(radious < 1)
+				radious = 1;
+			cvRectangle(imgMain, sp1,sp2, CV_RGB(0,255,255),1,8,0);
+	}
+	*/
+	//end of test
+	
+	CvSeq* seqHolesEnd = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
+	cvSeqPush( seqHolesEnd, &hipPoint );
+	cvSeqPush( seqHolesEnd, &kneePoint );
+	cvSeqPush( seqHolesEnd, &toePoint );
+	return seqHolesEnd;
+}
+
+
+/*
+ * takes input argument as the gray form of input frame and a temp image
+ * Returns the bounding rectangle of the contour having maximum height
+ * Draws the bounding rectangle of the largest contour on temp
+ */
+
+CvRect findLargestContour(IplImage* img,IplImage* temp, bool showContour)
+{
+	CvContourScanner scanner;
+	CvSeq *src_contour;
+	IplImage *tempcopy = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
+	cvCopy(img,tempcopy);
+	CvMemStorage* storage = cvCreateMemStorage(0);
+	scanner = cvStartFindContours(img,storage,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
+	cvZero(temp);
+	CvRect maxrect;
+	maxrect.x=0;maxrect.y=0;maxrect.width=0;maxrect.height=0;
+	while((src_contour = cvFindNextContour(scanner))!= 0)
+	{
+		CvRect rect = ((CvContour*)src_contour)->rect;
+		if((rect.height) < (img->height)/3)
+			continue;
+		if(rect.height > maxrect.height)
+		{
+			maxrect.x = rect.x;
+			maxrect.y =	rect.y;
+			maxrect.width = rect.width;
+			maxrect.height = rect.height;
+		}
+		cvDrawContours(temp,src_contour,cvScalarAll(255),cvScalarAll(255),0,-1);
+	}
+
+	//show temp image (contour) little
+	if(showContour) {
+		cvNamedWindow("contour",1);
+		cvResize(temp, temp, CV_INTER_LINEAR);
+
+		double scale = 4;
+		IplImage* tempSmall = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 );
+		cvResize( temp, tempSmall, CV_INTER_LINEAR );
+
+		cvShowImage("contour", tempSmall);
+	}
+	
+	cvReleaseMemStorage(&storage);
+	cvReleaseImage(&tempcopy);
+	return maxrect;
+}
+
+
+CvPoint FixHipPoint1(IplImage* img, CvPoint hip, CvPoint knee, double angle)
+{
+	CvPoint ptHK;
+	ptHK.x =0;ptHK.y=0;
+	CvMat *srcmat,src_stub;
+	srcmat = cvGetMat(img,&src_stub);
+	uchar *srcdata = srcmat->data.ptr;
+	int width = img->width;
+
+	//find at 3/2 of hip (surely under the hand)
+	int y=hip.y*.66 + knee.y*.33;
+
+	uchar *srcdataptr = srcdata + y*img->width;
+	int startX = 0;
+	int endX = 0;
+	bool found = false;
+	for(int x=0;x<width;x++)
+	{
+		if(srcdataptr[x] > 0)
+		{
+			if(!found) {
+				startX = x;
+				endX = x;
+				found = true;
+			}
+			endX ++;
+		}
+	}
+
+	//point will be more at right if there's more flexion
+	double mult;
+	double maxRight = .7; //maximum right
+	if(angle >= 180)
+		mult = .5;
+	else if(angle < 90)
+		mult = maxRight;
+	else {
+		double temp = maxRight -.5; //if 5, then will be added to 
+		double sum = ((180/angle) -1) *temp;
+		mult = .5 + sum;
+		printf("%f-%f-%f  ", angle, sum, mult);
+	}
+	
+	//ptHK.x = (startX + countX) /2;
+	ptHK.x = startX + (endX-startX)*mult;
+	printf("%d-%d-%d\n", startX, endX, ptHK.x);
+
+	ptHK.y = y;
+	
+	return ptHK;
+}
+
+CvPoint FixHipPoint2(IplImage* img, int hipFirstY, CvPoint knee, CvPoint ptHK)
+{
+			
+	/* this was hippoint in 1/3 of the leg (close to the hip but just below the hand)
+	 * now do a line from knee to this hippoint and cross this line with first hippoint and x axe
+	 * we will have the first hippoint but centered on the hip (without problems with the hand)
+	 */
+
+	CvPoint kneePrima;
+	kneePrima.x = knee.x - ptHK.x; 
+	kneePrima.y = knee.y - ptHK.y; 
+
+	/*
+	 * y = (kneePrima.y / kneePrima.x) * x + d
+	 * x = (kneePrima.x / kneePrima.y) * y - d
+	 * d = -x +(kneePrima.x / kneePrima.y) * y
+	 */
+
+	double d = -knee.x + ( (kneePrima.x / (double)kneePrima.y) * knee.y);
+
+	/*
+	 * x = (kneePrima.x / kneePrima.y) * y - d
+	 */
+	 
+	CvPoint HCenter;
+	HCenter.x =0; 
+	HCenter.y = hipFirstY;
+
+	HCenter.x = ( (kneePrima.x / (double)kneePrima.y) * HCenter.y ) - d;
+
+	/*
+	if(debug) {
+		printf("hipy(%d) ",hipFirstY);
+		printf("knee(%d,%d) ",knee.x, knee.y);
+		printf("ptHK(%d,%d) ",ptHK.x, ptHK.y);
+		printf("kneePrima(%d,%d) ",kneePrima.x, kneePrima.y);
+		printf("HCenter(%d,%d) ",HCenter.x, HCenter.y);
+		printf("kneePrima x/y:%.2f ", kneePrima.x / (double)kneePrima.y);
+		printf("d:%.1f", d);
+		printf("\n");
+	}
+	*/
+
+	return HCenter;
+}
+
+/* paints stick figure at end */
+void paintStick(IplImage *img, int lowestAngleFrame, CvSeq *hipSeq, CvSeq* kneeSeq, CvSeq *footSeq, 
+		bool showPoints, bool showLinesDiff, bool showLinesSame, bool onlyStartMinEnd, CvFont font) {
+	
+	//colors for start, end points, and up, down lines
+	CvScalar startColor = CV_RGB(0,0,255); //start blue
+	CvScalar minAngleColor = CV_RGB(255,0,0); //min angle red
+	CvScalar endColor = CV_RGB(0,255,0); //end green
+	CvScalar connectedWithPreviousColor = CV_RGB(255,255,0); //yellow
+	CvScalar unConnectedWithPreviousColor = CV_RGB(128,128,128); //grey
+	CvScalar currentColor;
+	int size = 0;
+	
+	bool lastFound = false;
+	bool neverFound = true;
+
+	for( int i = 0; i < hipSeq->total; i++ )
+	{
+		CvPoint hip = *CV_GET_SEQ_ELEM( CvPoint, hipSeq, i );
+		CvPoint knee = *CV_GET_SEQ_ELEM( CvPoint, kneeSeq, i );
+		CvPoint foot = *CV_GET_SEQ_ELEM( CvPoint, footSeq, i );
+
+		//if this point was found
+		if(!pointIsNull(hip)) {
+
+			//colors are different depending on phase
+			if(i < lowestAngleFrame)
+				currentColor = startColor;
+			else if(i > lowestAngleFrame)
+				currentColor = endColor;
+			else
+				currentColor = minAngleColor;
+
+			//size of some points is bigger, also decide if paint angle lines
+			bool paintAngleLines = true;
+			if(neverFound || i == lowestAngleFrame || i == hipSeq->total -1 )
+				size = 3;
+			else {
+				size = 1;
+				if(onlyStartMinEnd)
+					paintAngleLines = false;
+			}
+
+			if(showPoints) {
+				cvCircle(img,knee,size, currentColor,1,8,0);
+				cvCircle(img,hip,size, currentColor,1,8,0);
+				cvCircle(img,foot,size, currentColor,1,8,0);
+			}
+			if(showLinesDiff && paintAngleLines) {
+				cvLine(img,knee,hip,currentColor,1,1);
+				cvLine(img,knee,foot,currentColor,1,1);
+			}
+			if(showLinesSame) {
+				if(i>0) {
+					CvPoint hipOld = *CV_GET_SEQ_ELEM( CvPoint, hipSeq, i-1);
+					CvPoint kneeOld = *CV_GET_SEQ_ELEM( CvPoint, kneeSeq, i-1);
+					CvPoint footOld = *CV_GET_SEQ_ELEM( CvPoint, footSeq, i-1);
+
+					//only paint line if previous point was found
+					if(!pointIsNull(hipOld)) {
+						cvLine(img, hip, hipOld, connectedWithPreviousColor,1,1);
+						cvLine(img, knee, kneeOld, connectedWithPreviousColor,1,1);
+						cvLine(img, foot, footOld, connectedWithPreviousColor,1,1);
+					}
+				}
+			}
+			lastFound = true;
+			neverFound = false;
+		} else 
+			lastFound = false;
+	}
+	
+	//print text	
+	char *label = new char[10];
+	sprintf(label,"First");
+	cvPutText(img, label,cvPoint(20, 20),&font,startColor);
+	sprintf(label,"Min");
+	cvPutText(img, label,cvPoint(20, 40),&font,minAngleColor);
+	sprintf(label,"Last");
+	cvPutText(img, label,cvPoint(20, 60),&font,endColor);
+}

Added: trunk/src/angle/kneeAngleUtil.cpp
==============================================================================
--- (empty file)
+++ trunk/src/angle/kneeAngleUtil.cpp	Fri Oct  3 21:13:18 2008
@@ -0,0 +1,271 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Initally coded by (v.1.0):
+ * Sharad Shankar & Onkar Nath Mishra
+ * http://www.logicbrick.com/
+ * 
+ * Updated by:
+ * Xavier de Blas 
+ * xaviblas gmail com
+ *
+ *
+ */
+
+
+
+
+#include "opencv/cv.h"
+#include "opencv/highgui.h"
+#include <opencv/cxcore.h>
+#include "stdio.h"
+#include "math.h"
+#include<iostream>
+#include<fstream>
+#include<vector>
+#include <string>
+using namespace std;
+
+CvPoint findMiddle(CvPoint pt1, CvPoint pt2)
+{
+	return cvPoint((pt1.x+pt2.x)/2, (pt1.y+pt2.y)/2);
+}
+
+CvPoint findCenter(CvPoint pt1, CvPoint pt2)
+{
+	CvPoint center;
+	center.x=(pt1.x + pt2.x)/2 +1;
+	center.y=(pt1.y + pt2.y)/2 +1;
+	return center;
+}
+
+bool connectedWithPoint(CvPoint pt, CvPoint sp)
+{
+	if     (sp.x == pt.x -1 && sp.y == pt.y) //left
+		return true;
+	else if(sp.x == pt.x -1 && sp.y == pt.y-1) //upLeft
+		return true;
+	else if(sp.x == pt.x    && sp.y == pt.y-1) //up
+		return true;
+	else if(sp.x == pt.x +1 && sp.y == pt.y-1) //upRight
+		return true;
+	else if(sp.x == pt.x +1 && sp.y == pt.y  ) //right
+		return true;
+	else if(sp.x == pt.x +1 && sp.y == pt.y+1) //downRight
+		return true;
+	else if(sp.x == pt.x    && sp.y == pt.y+1) //down
+		return true;
+	else if(sp.x == pt.x -1 && sp.y == pt.y+1) //downLeft
+		return true;
+	//		else if(sp.y == pt.y -1) //special attention
+	//			return true;
+	else
+		return false;
+}
+
+CvRect seqRect(CvSeq *seq) {
+
+	int minx = 1000;
+	int miny = 1000;
+	int maxx = 0;
+	int maxy = 0;
+	for( int i = 0; i < seq->total; i++ )
+	{
+		CvPoint pt = *CV_GET_SEQ_ELEM( CvPoint, seq, i ); //seqPoint
+		if(pt.x < minx)
+			minx = pt.x;
+		if(pt.x > maxx)
+			maxx = pt.x;
+		if(pt.y < miny)
+			miny = pt.y;
+		if(pt.y > maxy)
+			maxy = pt.y;
+	}
+	
+	CvRect rect;
+
+	rect.x = minx;
+	rect.y = miny;
+	rect.width = maxx-minx;
+	rect.height = maxy-miny;
+
+	return rect;
+}
+
+
+CvPoint findCorner(CvSeq* seq, bool first)
+{
+	int minx= 1000;
+	int miny= 1000;
+	int maxx= 0;
+	int maxy= 0;
+	CvPoint pt;
+	if(first) {
+		pt.x=minx; pt.y=miny;
+	} else {
+		pt.x=maxx; pt.y=maxy;
+	}
+
+	for( int i = 0; i < seq->total; i++ ) {
+		CvPoint sp = *CV_GET_SEQ_ELEM( CvPoint, seq, i ); //seqPoint
+		if(first) {
+			if(sp.x < pt.x) 
+				pt.x = sp.x;
+			if(sp.y < pt.y) 
+				pt.y = sp.y;
+		} else {
+			if(sp.x > pt.x)
+				pt.x = sp.x;
+			if(sp.y > pt.y)
+				pt.y = sp.y;
+		}
+	}
+	return pt;
+}
+
+/* at first photogramm where knee or foot is detected (it will not be too horizontal) find it's width and use all the time to fix kneex
+ * at knee is called only done one time (because in max flexion, the back is line with the knee and there will be problems knowing knee width
+ * at foot is called all the time
+ */
+int FindWidth(IplImage* img, CvPoint kneeOrFoot)
+{
+	CvMat *srcmat,src_stub;
+	srcmat = cvGetMat(img,&src_stub);
+	uchar *srcdata = srcmat->data.ptr;
+	int width = img->width;
+
+	int y=kneeOrFoot.y;
+
+	uchar *srcdataptr = srcdata + y*img->width;
+	int countX = 0;
+	for(int x=kneeOrFoot.x-1;srcdataptr[x];x--)
+	{
+		countX ++;
+	}
+
+	return countX;;
+}
+
+double getDistance(CvPoint p1, CvPoint p2)
+{
+	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
+}
+
+
+bool upperSimilarThanLower(CvPoint hipPoint, CvPoint kneePoint, CvPoint footPoint)
+{
+	double upper = getDistance(kneePoint, hipPoint); 
+	double lower = getDistance(kneePoint, footPoint);
+	double big = 0; 
+	double little = 0;
+	
+	if(upper > lower) {
+		big = upper;
+		little = lower;
+	} else {
+		big = lower;
+		little = upper;
+	}
+
+//	if(debug)
+//		printf("upper(%.1f), lower(%.1f), big/little (%.2f)\n",upper, lower, big/(double)little);
+
+	//if one is not n times or more bigger than the other
+	//consider that if camera hides shoes and a bit more up, 2 times is risky in a maximal flexion
+	//consider also that this data is previous to fixing
+	double n = 2.5;
+	if(big / (double)little < n)
+		return true;
+	else 
+		return false;
+}
+
+bool pointIsNull(CvPoint pt) {
+	CvPoint notFoundPoint;
+	notFoundPoint.x = 0; notFoundPoint.y = 0;
+	if(pt.x == notFoundPoint.x && pt.y == notFoundPoint.y) 
+		return true;
+	else 
+		return false;
+}
+
+double findAngle(CvPoint p1, CvPoint p2, CvPoint pc) //pc is center point
+{
+	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);
+	return (180.0/M_PI)*acos(((d1.x*d2.x + d1.y*d2.y))/(double)(dist1*dist2));
+}
+
+double relError(double val1, double val2)
+{
+	if(val2-val1 == 0 || val2 == 0)
+		return -1;
+	else
+		return (val2-val1)/val2 *100;
+}
+
+int getMaxValue(CvSeq* seqGroups)
+{
+	int max = 0;
+	for( int i = 0; i < seqGroups->total; i++ ) {
+		int group = *CV_GET_SEQ_ELEM( int, seqGroups, i ); 
+		if(group > max)
+			max = group;
+	}
+	return max;
+}
+					
+void fusionateGroups(CvSeq* seqGroups, int g1, int g2) {
+	for( int i = 0; i < seqGroups->total; i++ ) {
+		int found = *CV_GET_SEQ_ELEM( int, seqGroups, i );
+		if(found == g2) {
+			cvSeqRemove(seqGroups, i);
+			cvSeqInsert(seqGroups, i, &g1);
+		}
+	}
+}
+
+int getGroup(int pointPos, CvPoint pt, CvSeq* seqPoints, CvSeq* seqGroups)
+{
+	//search in previous points
+	int group = -1;
+	for( int i = 0; i < pointPos; i++ ) {
+		CvPoint sp = *CV_GET_SEQ_ELEM( CvPoint, seqPoints, i ); 
+		if(connectedWithPoint(pt, sp)) { //if is connected with 
+			int tempGroup = *CV_GET_SEQ_ELEM( int, seqGroups, i );
+			if(group != -1 && //a group connected with that point was found
+					tempGroup != group) //that group was not the same group we just found now
+			{ 
+				//it was connected with another group, let's fusionate
+				fusionateGroups(seqGroups, tempGroup, group);
+			}
+			group = *CV_GET_SEQ_ELEM( int, seqGroups, i );
+		}
+	}
+
+	if(pointPos == 0) //return 0 is the first point
+		return 0;
+	else if(group == -1) //if not found, return a new group
+		return getMaxValue(seqGroups) +1;
+	else
+		return group; //return group found
+}



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