Face detection program bug

Hi guys, I'm currently trying to produce a facial detection application, but I seem to have some problems. My program, is able to recognise multiple users, and match their captured image to one saved in the database. However, if a person who has not registered is photographed, it is supposed open a pop-up of a picture of my choosing (in the code below I've chosen a picture of Mario) and tell the user that he/she is not in the database. The code for the condition of both recognizing and showing an unrecognised user is below.

The problem I have, is that when an unrecognised user is captured, it will still show user 1 or 2, instead of a "Mario" image. I'm unsure if it is the recognition algorithm (code also below) or my "if" statement that is at fault. I'm now trying with only 2 users to minimize the chance of errors. Can anyone help?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
void CzebraDlg::OnBnClickedCapturetrain()
{
else if( LearnOrRecognize == 2)  // CASE 2 (CAPTURE FOR RECOGNIZE)
	{
	sprintf(PicFname, "%s", "test.jpg");
	sprintf(TestFname, "%s", "test.txt");

	ofstream outfile;   //An object:myfile of type "ofstream" is created to allow the file to be opened for writing
	outfile.open(TestFname, ios::app);

	char *temp  = new char[50];
	
	sprintf(temp, "%s", "1 test.jpg");
	outfile << temp <<endl;

	cvSaveImage(PicFname, gregion);

	recognize();

IplImage* Identified_Person_Img;

		if (RESULT_NEAREST == 1) //Nearest refers to ID of person being recognized
		{
		cvNamedWindow( "ID01", 0 );
		cvResizeWindow( "ID01", 160, 160 );
		cvMoveWindow( "ID01", 673, 506 );
		Identified_Person_Img = cvLoadImage( "D:\\FYP\\01\\1.jpg", 1 );
		cvShowImage("ID01", Identified_Person_Img);
		EEE(node_number=0); //meant for hardware interfacing, not used
		}
		if (RESULT_NEAREST !=1)
		{
		 if (RESULT_NEAREST == 2)
		{
		cvNamedWindow( "ID02", 0 );
		cvResizeWindow( "ID02", 160, 160 );
		cvMoveWindow( "ID02", 673, 506 );
		Identified_Person_Img = cvLoadImage( "D:\\FYP\\02\\1.jpg", 1 );
		cvShowImage("ID02", Identified_Person_Img);
		EEE(node_number=1);
		}
}
		if (!(RESULT_NEAREST == 1) && !(RESULT_NEAREST == 2))
		{
		cvNamedWindow( "Unknown Face Detected", 0 );
		cvResizeWindow( "Unknown Face Detected", 160, 160 );
		cvMoveWindow( "Unknown Face Detected", 673, 506 );
		IplImage* UnknownFace;
		UnknownFace = cvLoadImage( "D:\\FYP\\MARIO1.jpg", 1 );
		IplImage *FUnknownFace = 0;
	              FUnknownFace = cvCreateImage(cvSize(160, 160),            
								UnknownFace->depth, UnknownFace->nChannels);
				  cvResize( UnknownFace, FUnknownFace, CV_INTER_LINEAR );
		cvShowImage("Unknown Face Detected", FUnknownFace);
		EEE(node_number=20);
		}
outfile.close();
}
}



Recognition function is below for reference and error checking.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void recognize()
{
	int i, nTestFaces  = 0;         // the number of test images
	CvMat * trainPersonNumMat = 0;  // the person numbers during training
	float * projectedTestFace = 0;

	// load test images and ground truth for person number
	nTestFaces = loadFaceImgArray("test.txt");

	// load the saved training data
	if( !loadTrainingData( &trainPersonNumMat ) ) return;

	// project the test images onto the PCA subspace
	projectedTestFace = (float *)cvAlloc( nEigens*sizeof(float) );

	int iNearest, nearest, truth;

	for(i=0; i<nTestFaces; i++)
	{
		// project the test image onto the PCA subspace
		cvEigenDecomposite
			(
				faceImgArr[i],
				nEigens,
				eigenVectArr,
				0, 0,
				pAvgTrainImg,
				projectedTestFace);

		iNearest = findNearestNeighbor(projectedTestFace);
		truth    = personNumTruthMat->data.i[i];
		nearest  = trainPersonNumMat->data.i[iNearest];
		
		}
        RESULT_NEAREST = nearest;
		RESULT_TRUTH   = truth;
}


Function that gives values to the one above's code is below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int findNearestNeighbor(float * projectedTestFace)
{
	double leastDistSq = DBL_MAX;
	int i, iTrain, iNearest = 0;

	for(iTrain=0; iTrain<nTrainFaces; iTrain++)
	{
		double distSq=0;

		for(i=0; i<nEigens; i++)
		{
			float d_i =
				projectedTestFace[i] -
				projectedTrainFaceMat->data.fl[iTrain*nEigens + i];
			distSq += d_i*d_i / eigenValMat->data.fl[i];
			
		}

		if(distSq < leastDistSq)
		{
			leastDistSq = distSq;
			iNearest = iTrain;
		}
	}

	return iNearest;
}


I'm using MFC for the GUI creation, but I don't think that should be a problem as of now. Thanks a lot for any help in advance.



Last edited on
- Please use a debugger, it will take lesser time and tell you more than a forum.

- Use switch-case instead of the cryptic if-else.

One possible cause of error is incorrect initialisation of RESULT_NEAREST
Hello there, I've tidied up the code like you said (code below) and used the debugger.

I tried debugging the values of "RESULT_NEAREST". The values are correct when different users that are already registered inside are captured, but I just noticed, that it always gives itself a value of "1" when an unrecognized person is captured, causing the problem. Is there a fix for this? Thanks for the reply.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
IplImage* Identified_Person_Img;

		if (RESULT_NEAREST == 1) //Nearest refers to ID of person being recognized
		{
		cvNamedWindow( "ID01", 0 );
		cvResizeWindow( "ID01", 160, 160 );
		cvMoveWindow( "ID01", 673, 506 );
		Identified_Person_Img = cvLoadImage( "D:\\FYP\\01\\1.jpg", 1 );
		cvShowImage("ID01", Identified_Person_Img);
		EEE(node_number=0);  //for hardware interfacing, ignore for now
		}
		else if (RESULT_NEAREST == 2) //this 'else if' is here as I may add more users later
		{
		cvNamedWindow( "ID02", 0 );
		cvResizeWindow( "ID02", 160, 160 );
		cvMoveWindow( "ID02", 673, 506 );
		Identified_Person_Img = cvLoadImage( "D:\\FYP\\02\\1.jpg", 1 );
		cvShowImage("ID02", Identified_Person_Img);
		EEE(node_number=1);
		}
                else
		{
		cvNamedWindow( "Unknown Face Detected", 0 );
		cvResizeWindow( "Unknown Face Detected", 160, 160 );
		cvMoveWindow( "Unknown Face Detected", 673, 506 );
		IplImage* UnknownFace;
		UnknownFace = cvLoadImage( "D:\\FYP\\MARIO1.jpg", 1 );
		IplImage *FUnknownFace = 0;
	              FUnknownFace = cvCreateImage(cvSize(160, 160),            
								UnknownFace->depth, UnknownFace->nChannels);
				  cvResize( UnknownFace, FUnknownFace, CV_INTER_LINEAR );
		cvShowImage("Unknown Face Detected", FUnknownFace);
		EEE(node_number=20);
		}
Then the problem is in the other 2 functions. I do not understand the algorithm and the logic without the complete code as these snippets just provide some declarations and miss the global variables and structure definitions and initialisation.

The only way forward is to subsequently debug on any function that is returning incorrect result and then any other function being called from inside... to check the values after every iteration of your loop...

Anybody will do that only... Please provide the complete code and ask specifically if you need a code review.

programming is a stepwise process...

You cant just hope to get good learnings from this project by posting different problems in different sections on www.cplusplus.com...!!!
Hello, thanks for the feedback. Sorry for any inconvenience caused. I'll see what I can do with the debugger. At the same time, I'm also trying to make the code I posted easier to read by optimizing it, but I seem to have hit a small problem. When I try to recognize the image with the code below, it returns a blank pop-up. Using the debugger, my values when I click the button are correct so I think it is a problem is in my syntax with how I called the pop-up and the file directory. Is there any error?

1
2
3
4
5
6
sprintf(temp, "%s", RESULT_NEAREST); //not really sure if this is correct, best I could find
		cvNamedWindow( "ID", 0 );
		cvResizeWindow( "ID", 160, 160 );
		cvMoveWindow( "ID", 673, 506 );
		Identified_Person_Img = cvLoadImage( "D:/FYP/0%s/1.jpg", 1 ); //actual directory is "D:/FYP/<ID of user, eg. 01,02,etc>/1.jpg"
		cvShowImage("ID", Identified_Person_Img);


This is meant to replace the entire chunk I posted one post ago. Sorry again for any trouble, when this is done I think it would be easier for the debugger to help. Thanks in advance!
I dont know anything about MFC, so I wont be able to help in any way for that matter.
Any syntax error would be pointed out by the compiler.

But i can point out 2 errors:

Line 1: sprintf would require you to specify %d because RESULT_NEAREST is a decimal value, not a string.
See http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

Line 5: The file path to be provided to cvLoadImage() can only be a constant string, you cannot format a string at anytime using a format specifier. If you want to make the string using the user ids, you have to do it before you pass it to cvLoadImage().

Check the MSDN manuals to look for the function signatures. I am sure you can find it there.

--------------------------
There is no inconvinience caused in any manner.
A sugggestion however is to first look for online manuals/references and read the books to know about how to use the functions you are using rather than just going out coding and finding errors.
Topic archived. No new replies allowed.