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?
Code:
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.
Code:
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
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. If you need to see the entire code that these snippets are taken from, I have attached it (zebraDlg.cpp).
Last edited by meepokman; June 17th, 2010 at 07:48 PM.
Hello there, I've tidied the codes up like you suggested (posted below). I also just noticed that within the "recognize" function, the 'for' loop to that examines the test image will keep going as far as the number of images in the database, instead of exiting. Could this be a problem?
I added a 'break' after assignment to "RESULT_NEAREST" but it did not seem to help. Is there any possible solution to this?
Code:
void recognize() //full function posted at first post
{
.....
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];
break; //just added in
}
RESULT_NEAREST = nearest;
RESULT_TRUTH = truth;
Tidied up sections
Code:
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) //I have left this in as I will be increasing the number of users
{
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);
}
Sorry the the double post, but I cannot edit my post, so I've reposted the full "recognize" function below with proper code tags. If any admin can help, could my earlier post be edited by you to add in the code tags? Apologies for any inconvenience caused.
Code:
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;
}
This is a problem for the debugger to solve. Have you tried stepping through the code?
Hi, 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.
Hi, 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.
You need to step through the code and find out where it's going wrong. And please properly indent your code. It's very hard to read like that.
Hi guys, I'm currently trying to produce a facial detection application, but I seem to have some problems.
Why do you repeatedly do this?
Code:
char *temp = new char[50];
First, your code has a memory leak, since you never deallocated the memory with delete[]
Second, there is no need to allocate memory. The array is set to 50 characters, so why didn't you just declare an array of 50 chars?
Code:
char temp[50]; // this is all you need to do
Your code unnecessarily calls new[], slowing down your program, and if you call that routine many times, your application is also eating up the free-store memory.
Third, what if whatever you're putting into this array has more than 50 characters? Where is the check for exceeding the 50 character (49 if it's null terminated) limit?
The only difference is the ID number and the Person number.
A sign of a good programmer is one that sees obvious repeated code, and doesn't write repeated code. When you realize you're writing the same thing over and over again 20+ times, with hardly any difference in what you're writing, then you should realize that you're doing something inefficiently or unnecessarily.
Hello Paul, thanks a lot for your suggestions. I've implemented and modified them accordingly. Following what you said, I'm trying to simplify the code so it is easier to read before I try to solve any more problems. For the "recognize" function, I'm trying to do what you did but I seem to have some difficulties. 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 with how I called the pop-up and the file directory. Is there any error?
Code:
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);
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.