⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 caam.cpp

📁 face recognition test source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "stdafx.h"

#include "CAAM.h"
#include "CMatPtr.h"
#include "utilcpp.h"
#include "str.h"
#include "def.h"
#include "error.h"
#include "cvect.h"
#include "str2.h"

#include "lvq.h"

extern "C" {
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
}

#define INDETERMINATE		-5
void NChar(char *buf, int n);

CAAM::CAAM()
	{
	int i;
	
	pTrainingDB = NULL;
	pEFace = NULL;
	pEVect = NULL;
	pEVal = NULL;
	
	pReconstructionDB = NULL;
	pReconstructedDB = NULL;
	pReconstructedMat = NULL;
	pReconstructionCmp = NULL;
	
	pRecognizeDB = NULL;						
	pRecognizedDB = NULL;						
	pRecognizedMat = NULL;
	pRecognizeCmp = NULL;
	pMetDB = NULL;
	pMetCmp = NULL;
	pSammon = NULL;
	pCategorizeDB = NULL;
	
	for (i = 0; i < CMD_MAX; i++)
		bCommand[i] = FALSE;
	}

CAAM::~CAAM()
	{
	if (pSammon != NULL)
		delete pSammon;
		
	if (pEFace != NULL)
		delete pEFace;
		
	if (pEVal != NULL)
		delete pEVal;
	if (pEVect != NULL)
		{
		pEVect->FreeCol();
		delete pEVect;
		}
		
	if (pCategorizeDB != NULL)
		delete pCategorizeDB;
	if (pTrainingDB != NULL)
		delete pTrainingDB;
	if (pReconstructionDB != NULL)
		delete pReconstructionDB;
	if (pReconstructedDB != NULL)
		delete pReconstructedDB;
	if (pReconstructedMat != NULL)
		delete pReconstructedMat;
	if (pMetDB != NULL)
		delete pMetDB;
	if (pRecognizeDB != NULL)
		delete pRecognizeDB;
	if (pRecognizedDB != NULL)
		delete pRecognizedDB;
	if (pRecognizedMat != NULL)
		delete pRecognizedMat;
	if (pMetCmp != NULL)
		delete pMetCmp;
	if (pReconstructionCmp != NULL)
		delete pReconstructionCmp;
	if (pRecognizeCmp != NULL)
		delete pRecognizeCmp;
	}

/*****************************************************************************************
* Build the memory and compute its eigenvectors
* The Training set (pTrainingDB) has to be loaded before the calling to this fct.
*****************************************************************************************/
int CAAM::Build(long leigen)
	{
	long number; 
	long lFace = pTrainingDB->GetNumFace();
	long lPixel = pTrainingDB->GetNumPixel();
	CMatrixPtr *pX;											/*Matrix containing the training set, whose each columns points to a face data*/
	CMatrixPtr *pQ;
	
	Msg(1, str_AAM_BUILD_START);
	
	lRow = lPixel;
	lCol = lFace;
	if (leigen == -1)
		lEigen = lFace;
	else
		lEigen = lmin(leigen, lFace);
	
	pX = new CMatrixPtr(lRow, lCol);						/*Construct the matrix whose each columns points to a face data*/
	pQ = new CMatrixPtr(lCol, lCol);						/*Construct an intermediate matrix*/
	pQ->AllocateCol();										/*Allocate memory to store its columns*/
	pEVal = new CDiag(lCol);								/*Diagonal matrix containing the eigenvalues*/
	
	DBtoMat(pX, pTrainingDB);								/*Copy the pointer of the faces' data into the one of the columns' matrix*/
	pX->NormalizeCol();										/*Normalize each face*/
	Msg(0, str_AAM_BUILD_NORMALIZED);
	            
	pX->InnerProduct(pQ);									/*pQ = transpose(pX) * pX */
	Msg(0, str_AAM_BUILD_INNER);
	
	pQ->Eigen(pEVal, lEigen);								/*put in pQ its eigenvectors and in pEVal its eigenvalues*/
	Msg(0, str_AAM_BUILD_EIGEN1);
	
	Sort(pQ, pEVal);											/*Sort in descending order the eigenvalues in order to put*/
	Msg(0, str_AAM_BUILD_SORT);							/*eigenvectors whose have the biggest eigenvalues at the biginning of the matrix*/
	
	lEigen = lmin(lEigen, pQ->GetCol());            /*Sort may suppress columns, lEigen has to be les or equal than the number of col of pQ*/
	pEVect = new CMatrixPtr(lRow, lEigen);				/*Construct the eigenvector matrix*/
	pEVect->AllocateCol();									/*Allocate memory to store its columns*/
	
	if (leigen == -1 && number == 0)										
		pEVect->Multiply(pX, pQ);							/*pEVect = pX * pQ*/
	else
		pEVect->Multiply(pX, pQ, TRUE, lPixel, lEigen);		/*the same but this one is executed if the user asked for less eigenvectors*/
		
	pEVal->Pow(-0.5);										/*pEVal = PEVal ^ -1/2*/
	if (leigen == -1 && number == 0)
		pEVect->Multiply(pEVal);							/*pEVect = pEVect * pEVal*/
	else	
		pEVect->Multiply(pEVal, TRUE);						/*the same but this one is executed if the user asked for less eigenvectors*/
	pEVal->Pow(-2);											/*Reset the eigenvalues to their real values*/
	delete pQ;												/*delete the intermediate matrix*/
	delete pX;												/*delete the matrix storing the training set (but the set remains in the pTrainingDB object)*/
	GetEigenDB()->Copy(pEVect, pEVal);						/*Copy the pointer of each eigenvectors into the pointer of each face's data*/
	
	Msg(-1, str_AAM_BUILD_DONE, lEigen);
	return 0;
	}

/*****************************************************************************************
* Reconstruct the faces stored in pReconstructionDB
* pReconstructionDB has to be loaded before the calling to this fct.
*****************************************************************************************/
int CAAM::Reconstruct()
	{
	CMatrixPtr	*pReconstructionMat;						/*Matrix containing the pixel of the faces to be reconstructed*/
	CDiag		*pReconstructionCos;							/*Cosine between the real faces and the reconstructed ones*/
	long lRow, lCol;
	long lFace = pReconstructionDB->GetNumFace();
	long lPixel = pReconstructionDB->GetNumPixel();
	
	Msg(1, str_AAM_RECONSTRUCTION_START);
	
	lRow = lPixel;
	lCol = lFace;
	pReconstructionMat = new CMatrixPtr(lRow, lCol);
	pReconstructedMat = new CMatrixPtr(lRow, lCol);
	pReconstructedMat->AllocateCol();
	pReconstructionCmp = new CMatrix(lEigen, lCol);
	pReconstructionCos = new CDiag(lFace);
	pReconstructedDB = new CFaceDB();
	
	DBtoMat(pReconstructionMat, pReconstructionDB);	/*Copy the pointer of the faces' data into the one of the columns' matrix*/
	
	pReconstructionMat->NormalizeCol();					/*Normalize each face*/
	Msg(0, str_AAM_RECONS_NORMALIZED);
	
	FaceToCmp(pReconstructionCmp, pReconstructionMat);		
		/*Compute the composants of the unknown faces*/
	
	CmpToFace(pReconstructedMat, pReconstructionCmp);		
		/*Compute a set of faces from a set of composants*/
	
	ComputeCos(pReconstructionCos, pReconstructionMat, pReconstructedMat);
	
	pReconstructedDB->Copy(pReconstructedMat, pReconstructionCos);
		/*Copy the pointer of each eigenvectors into the pointer of each face's data*/
	
	delete pReconstructionMat;
	delete pReconstructionCos;
	Msg(-1, str_AAM_RECONSTRUCTION_DONE, lFace);
	return 0;
	}

/*****************************************************************************************
* Recognize the faces stored in pRecognizeDB.
* pRecognizeDB has to be loaded before the calling to this fct.
* It can, of course, recognize only the people previously seen. The composants of those people
* are stored in the pMetCmp matrix. If the face database pMetDB is null, it assume that those
* people are actually the people of the training set. So, in that case, this fct compute the
* composants of the training set at its beginning.
*****************************************************************************************/
int CAAM::Recognize(int nElect, BOOL bRecons)
	{
	CMatrixPtr	*pRecognizeMat = NULL;					/*Matrix containing the pixel of the faces to be recognized by th memory*/
	CMatrixPtr	*pRecognizedCmp = NULL;					/*Composants of faces of the already met people, each column correspond to a recognized face*/
	CDiag			*pRecognizeCos;							/*Cosine between the original face to be recognized and the face known recognized face*/
	CMatrix		*pAssociation = NULL;					/*At the end of the process pAssociation[n] will be equal to the number of the meeting face which looks the most like the nth face to recognize*/
	char Name1[64];
	char Name2[64];
	
	long lMetFace, lRecFace, lCorrect, l;
	long lPixel;
	CMatrixPtr *pX = NULL;                          /*Matrix containing the training set, whose each columns points to a face data*/
	float fPercent, fProb;											
	BOOL bMet = TRUE;
		
	Msg(1, str_AAM_RECOGNIZE_START);
	
	if (pMetDB == NULL)
		{															/*The met people are those in the training set*/
		pMetDB = pTrainingDB;
		bMet = FALSE;
		}
	
	lPixel  = pMetDB->GetNumPixel();
	lMetFace = pMetDB->GetNumFace();
	
	lRow = lPixel;
	lCol = lMetFace;
	pX = new CMatrixPtr(lRow, lCol);						/*Construct the matrix whose each columns points to a face data*/
	pMetCmp = new CMatrixPtr(lEigen, lCol);
	pMetCmp->AllocateCol();									/*Allocate memory to store its columns*/
	
	DBtoMat(pX, pMetDB);										/*Copy the pointer of the faces' data into the one of the columns' matrix*/
	pX->NormalizeCol();
	Msg(0, str_AAM_MEET_NORMALIZED);
	
	FaceToCmp(pMetCmp, pX);									/*Compute the composants of the training set*/
	delete pX;
	
	lRecFace = pRecognizeDB->GetNumFace();
	
	pRecognizeMat = new CMatrixPtr(lRow, lRecFace);
	pRecognizedMat = new CMatrixPtr(lRow, lRecFace);
	pRecognizedMat->AllocateCol();
	pRecognizeCmp = new CMatrix(lEigen, lRecFace);
	pRecognizedCmp = new CMatrixPtr(lEigen, lRecFace);
	pRecognizeCos = new CDiag(lRecFace);
	pRecognizedDB = new CFaceDB();
	
	if (strcmp(pMetDB->GetFaceName(1), "") != 0 && strcmp(pRecognizeDB->GetFaceName(1), "") != 0)
		pAssociation = new CMatrix(lRecFace, 2);
	else
		pAssociation = NULL;
	
	DBtoMat(pRecognizeMat, pRecognizeDB);
	pRecognizeMat->NormalizeCol();
	Msg(0, str_AAM_RECOG_NORMALIZED);
	
	FaceToCmp(pRecognizeCmp, pRecognizeMat);
	
	RecognizeCmp(pRecognizedCmp, pRecognizeCmp, pMetCmp, pAssociation, nElect, pMetDB);
	
	if (bRecons == TRUE)
		{
		CmpToFace(pRecognizedMat, pRecognizedCmp);
		
		ComputeCos(pRecognizeCos, pRecognizedMat, pRecognizeMat);
		
		pRecognizedDB->Copy(pRecognizedMat, pRecognizeCos);
		}
			
	delete pRecognizeMat;
	delete pRecognizedCmp;
	delete pRecognizeCos;
	if (pAssociation != NULL)
		{															/*If Face's name are given (by the user) for the met (or the training) database and for the faces to be recognized,*/
		lCorrect = 0;											/*Calculate the number of correct recognitions*/
		fProb = 0.0;
		pAssociation->Lock();
		for (l = 1; l <= lRecFace; l++)
			{
			if (pAssociation->GetAt(l, 1) == INDETERMINATE)
				{													/*Impossible to recognize the face*/
				Msg(0, "INDETERMINATE:   %s -> ???", pRecognizeDB->GetFaceName(l));
				}
			else
				{
				strcpy(Name1, pMetDB->GetFaceName(pAssociation->GetAt(l, 1)));
				strcpy(Name2, pRecognizeDB->GetFaceName(l));
				if (strcmp(Name1, Name2) == 0)
					{
					lCorrect++;
					Msg(0, str_RECOGNITION_RESULT_Y, Name2, Name1, pAssociation->GetAt(l, 2));
					fProb += pAssociation->GetAt(l, 2);
					}
				else
					Msg(0, str_RECOGNITION_RESULT_N, Name2, Name1, pAssociation->GetAt(l, 2));
				}
			}
		
		pAssociation->Unlock();
		fPercent = (float)lCorrect / (float)lRecFace;
		Msg(-1, str_AAM_RECOGNIZE_PERCENT, lRecFace, lCorrect, fPercent*100.0);
		Msg(0, "Average prob. of good recognition = %.1f", fProb/(float)lCorrect);
		}                                               
	else
		Msg(-1, str_AAM_RECOGNIZE_DONE, lRecFace);
	if (bMet == FALSE)
		{
		pMetDB = NULL;
		}
	return 0;
	}

/*****************************************************************************************
* Categorize the faces stored in pCategorizeDB. This categorization is done with the LVQ program
* pCategorizeDB has to be loaded before the calling to this fct.
* The learning stage of LVQ is achieved with the faces of pMetDB. If the face database pMetDB is 
* null, it assume that those faces are actually the faces of the training set. So, in that case, 
* this fct compute the composants of the training set at its beginning.
*****************************************************************************************/
int CAAM::Categorize(/*PFILECMD pcmd*/PFILESTATE fs)
	{
	CMatrixPtr	*pCategorizeMat = NULL;					/*Matrix containing the pixel of the faces to be recognized by th memory*/
	CMatrix	*pCategorizeCmp = NULL;						/*Composants of faces of the already met people, each column correspond to a recognized face*/
	
	long lMetFace, lCatFace, l;
	long lPixel;
	CMatrixPtr *pX = NULL;                          /*Matrix containing the training set, whose each columns points to a face data*/
	BOOL bMet = TRUE;
	float total;
		
	Msg(1, str_AAM_CATEGORIZE_START);
	
	if (pMetDB == NULL)
		{															/*The met people are those in the training set*/
		pMetDB = pTrainingDB;
		bMet = FALSE;
		}
	
	lPixel  = pMetDB->GetNumPixel();
	lMetFace = pMetDB->GetNumFace();
	
	lRow = lPixel;
	lCol = lMetFace;
	pX = new CMatrixPtr(lRow, lCol);						/*Construct the matrix whose each columns points to a face data*/
	pMetCmp = new CMatrixPtr(lEigen, lCol);
	pMetCmp->AllocateCol();									/*Allocate memory to store its columns*/
	
	DBtoMat(pX, pMetDB);										/*Copy the pointer of the faces' data into the one of the columns' matrix*/
	pX->NormalizeCol();
	Msg(0, str_AAM_MEET_NORMALIZED);
	
	FaceToCmp(pMetCmp, pX);									/*Compute the composants of the training set*/
	delete pX;
	
	lCatFace = pCategorizeDB->GetNumFace();
	
	pCategorizeMat = new CMatrixPtr(lRow, lCatFace);
	pCategorizeCmp = new CMatrix(lEigen, lCatFace);
	
	DBtoMat(pCategorizeMat, pCategorizeDB);
	pCategorizeMat->NormalizeCol();
	Msg(0, str_AAM_CATEG_NORMALIZED);
	
	FaceToCmp(pCategorizeCmp, pCategorizeMat);
   
   //put name into the matrix
   for (l = 1; l <= lMetFace; l++)
   	{
   	pMetCmp->SetColName(l, pMetDB->GetFaceName(l));
   	}
   
   for (l = 1; l <= lCatFace; l++)
   	{
   	pCategorizeCmp->SetColName(l, pCategorizeDB->GetFaceName(l));
   	}

#define UNDEF	0
#define INIT	1
#define LEARN	2
   
	//Categorization
	LVQPARAMS lvq;
	int nState = UNDEF;
	LVQInit(&lvq);
	BOOL bSammon;	
	lvq.pconfusion = NULL;
	if (/*pcmd == NULL*/fs->num_cmd == 0)
		{	/*default categorization*/
		lvq.noc 			= 9;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -