人脸识别系统
这个学期的软件工程作业----人脸识别系统, 基本功能还是实现了, 具体思路从国外一篇博客
学习而得,
http://www.shervinemami.info/faceRecognition.html, 写的非常好. 具体实现的方法呢,
我就不讲解了, 看了就懂. 需要完整代码可以留言. 还是前面总结的问题"道"与"术"的问题, 学习要
学习解决方法的思路.
难点: 人脸库的制作, 人脸的照片需要计算出特征向量, PCA主成分析法. 提高人脸识别精确度需要自己
根据具体情况取照片. 以下是我的读入人脸的train.txt文件(部分). 我用的是每人20张照片, 实验证明
相识度计算出来大概是40%~60%左右.
1 shanghe tt\shanghe\1.jpg
1 shanghe tt\shanghe\2.jpg
1 shanghe tt\shanghe\3.jpg
2 zhijie tt\zijie\1.jpg
2 zhijie tt\zijie\2.jpg
2 zhijie tt\zijie\3.jpg
3 haoru tt\haoru\1.jpg
3 haoru tt\haoru\2.jpg
3 haoru tt\haoru\3.jpg
4 benson tt\jiayong\1.jpg
4 benson tt\jiayong\2.jpg
4 benson tt\jiayong\3.jpg
贴一些核心代码:(不完整, 不熟悉的代码不要随便用!!!)
//计算欧拉距离
//寻找最接近的图像
int findNearestNeighbor(float * projectedTestFace)
{
double leastDistSq = DBL_MAX;
//定义最小距离,并初始化为无穷大
int i, iTrain, iNearest = 0;
for(iTrain=0; iTrain
{
double distSq=0;
for(i=0; i
{
float d_i =
projectedTestFace[i] -
projectedTrainFaceMat->data.fl[iTrain*nEigens + i];
distSq += d_i*d_i; // Euclidean算法计算的距离
}
if(distSq < leastDistSq)
{
leastDistSq = distSq;
iNearest = iTrain;
}
}
fConfidence = 1.0f - sqrt( leastDistSq / (float)(nTrainFaces * nEigens) ) / 255.0f;
iCount++;
if( fConfidence > thres )
recCount++;
printf("Confidence = %f\n",fConfidence);
if(fConfidence < 0.40) return -1;
//根据具体情况设置阀值
return iNearest;
}
//主成分分析
void doPCA()
{
int i;
CvTermCriteria calcLimit;
CvSize faceImgSize;
// 自己设置主特征值个数
nEigens = nTrainFaces-1;
//分配特征向量存储空间
faceImgSize.width
= faceImgArr[0]->width;
faceImgSize.height = faceImgArr[0]->height;
eigenVectArr = (IplImage**)cvAlloc(sizeof(IplImage*) * nEigens);
//分配个数为住特征值个数
for(i=0; i
eigenVectArr[i] = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
//分配主特征值存储空间
eigenValMat = cvCreateMat( 1, nEigens, CV_32FC1 );
// 分配平均图像存储空间
pAvgTrainImg = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
// 设定PCA分析结束条件
calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);
// 计算平均图像,特征值,特征向量
cvCalcEigenObjects(
nTrainFaces,
(void*)faceImgArr,
(void*)eigenVectArr,
CV_EIGOBJ_NO_CALLBACK,
0,
0,
&calcLimit,
pAvgTrainImg,
eigenValMat->data.fl);
cvNormalize(eigenValMat, eigenValMat, 1, 0, CV_L1, 0);
}
//加载txt文件的列举的图像
int loadFaceImgArray(char * filename)
{
char *faceCascadeFilename = "haarcascade_frontalface_alt2.xml";
CvHaarClassifierCascade *cascade;
cascade = (CvHaarClassifierCascade *)cvLoad(faceCascadeFilename,0,0,0);
CvRect rc;
FILE * imgListFile = 0;
char imgFilename[512];
int iFace, nFaces=0;
num = 0;
char temp[512];
if( !(imgListFile = fopen(filename, "r")) )
{
fprintf(stderr, "Can\'t open file %s\n", filename);
return 0;
}
// 统计人脸数
while( fgets(imgFilename, 512, imgListFile) ) ++nFaces;
rewind(imgListFile);
// 分配人脸图像存储空间和人脸ID号存储空间
faceImgArr
= (IplImage **)cvAlloc( nFaces*sizeof(IplImage *) );
personNumTruthMat = cvCreateMat( 1, nFaces, CV_32SC1 );
for(iFace=0; iFace
{
// 从文件中读取序号和人脸名称
fscanf(imgListFile,
"%d %s %s", personNumTruthMat->data.i+iFace, temp, imgFilename);
if( num != *(personNumTruthMat->data.i+iFace) )
{
strcpy(name[num], temp);
num = *(personNumTruthMat->data.i+iFace);
}
// 加载人脸图像
faceImgArr[iFace] = cvLoadImage(imgFilename, CV_LOAD_IMAGE_GRAYSCALE);
if( !faceImgArr[iFace] )
{
fprintf(stderr, "Can\'t load image from %s\n", imgFilename);
return 0;
}
rc = detectFaceInImage(faceImgArr[iFace], cascade);
if(rc.width == -1 && rc.height == -1) return -1;
cvSetImageROI(faceImgArr[iFace], rc);
IplImage *temp = cvCreateImage(cvSize(200, 250), faceImgArr[iFace]->depth, faceImgArr[iFace]->nChannels);
cvResize(faceImgArr[iFace], temp, CV_INTER_LINEAR);
cvResetImageROI(faceImgArr[iFace]);
faceImgArr[iFace] = processedImage(temp);
//
faceImgArr[iFace] = cvCloneImage(temp);
//
cvSaveImage(imgFilename, faceImgArr[iFace]);
printf("%d\n", iFace+1);
}
fclose(imgListFile);
return nFaces;
}
//图片预处理
IplImage* processedImage(IplImage *imageSrc)
{
IplImage *imageProcessed;
IplImage *imageGrey;
if(imageSrc->nChannels == 3)
{
imageGrey = cvCreateImage(cvGetSize(imageSrc), IPL_DEPTH_8U, 1);
cvCvtColor( imageSrc, imageGrey, CV_BGR2GRAY );
}
else
{
imageGrey = imageSrc;
}
imageProcessed = cvCreateImage( cvSize(200, 200), IPL_DEPTH_8U, 1 );
cvResize(imageGrey, imageProcessed, CV_INTER_LINEAR);
cvEqualizeHist(imageProcessed, imageProcessed);
return imageProcessed;
}
结果展示:
精确度有80%, 出奇高这次, 呵呵~~可能代码发现我要把它保存好. 这个学期学习opencv还是很好玩的.
自己继续加油吧!!!