📄 caam.cpp
字号:
#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 + -