opencv - 在 OpenCV 上实现特征脸

标签 opencv computer-vision face-detection

我正在尝试在 VS2010 中使用 OpenCV 实现特征脸算法。我使用这个网站作为引用:http://www.cognotics.com/opencv/servo_2007_series/part_5/index.html

我在实现它时遇到了一些问题,对此我几乎没有疑问。

我已经将 VS2010 配置为包含所有库。

代码在这里:

//recognize.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"


#include <stdio.h>
#include <string.h>
#include "cv.h"
#include "cvaux.h"
#include "highgui.h"


//// Global variables
IplImage ** faceImgArr        = 0; // array of face images
CvMat    *  personNumTruthMat = 0; // array of person numbers
int nTrainFaces               = 0; // the number of training images
int nEigens                   = 0; // the number of eigenvalues
IplImage * pAvgTrainImg       = 0; // the average image
IplImage ** eigenVectArr      = 0; // eigenvectors
CvMat * eigenValMat           = 0; // eigenvalues
CvMat * projectedTrainFaceMat = 0; // projected training faces


//// Function prototypes
void learn();
void recognize();
void doPCA();
void storeTrainingData();
int  loadTrainingData(CvMat ** pTrainPersonNumMat);
int  findNearestNeighbor(float * projectedTestFace);
int  loadFaceImgArray(char * filename);
void printUsage();


//////////////////////////////////
// main()
//
void main( int argc, char** argv )
{
    char c;
    // validate that an input was specified
    if( argc != 2 )
    {
        printUsage();
        return;
    }

    if( !strcmp(argv[1], "train") ) learn();
    else if( !strcmp(argv[1], "test") ) recognize();
    else
    {
        printf("Unknown command: %s\n", argv[1]);
        printUsage();
    }
}


//////////////////////////////////
// learn()
//
void learn()
{
    int i, offset;

    // load training data
    nTrainFaces = loadFaceImgArray("C:/Users/HP/Desktop/OpenCV/train.txt");
    if( nTrainFaces < 2 )
    {
        fprintf(stderr,
                "Need 2 or more training faces\n"
                "Input file contains only %d\n", nTrainFaces);
        return;
    }

    // do PCA on the training faces
    doPCA();

    // project the training images onto the PCA subspace
    projectedTrainFaceMat = cvCreateMat( nTrainFaces, nEigens, CV_32FC1 );
    offset = projectedTrainFaceMat->step / sizeof(float);
    for(i=0; i<nTrainFaces; i++)
    {
        //int offset = i * nEigens;
        cvEigenDecomposite(
            faceImgArr[i],
            nEigens,
            eigenVectArr,
            0, 0,
            pAvgTrainImg,
            //projectedTrainFaceMat->data.fl + i*nEigens);
            projectedTrainFaceMat->data.fl + i*offset);
    }

    // store the recognition data as an xml file
    storeTrainingData();
}


//////////////////////////////////
// recognize()
//
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("C:/Users/HP/Desktop/OpenCV/test.txt");
    printf("%d test faces loaded\n", nTestFaces);

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

    // project the test images onto the PCA subspace
    projectedTestFace = (float *)cvAlloc( nEigens*sizeof(float) );
    for(i=0; i<nTestFaces; i++)
    {
        int iNearest, nearest, truth;

        // 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];

        printf("nearest = %d, Truth = %d\n", nearest, truth);
    }
}


//////////////////////////////////
// loadTrainingData()
//
int loadTrainingData(CvMat ** pTrainPersonNumMat)
{
    CvFileStorage * fileStorage;
    int i;

    // create a file-storage interface
    fileStorage = cvOpenFileStorage( "C:/Users/HP/Desktop/OpenCV/facedata.xml", 0, CV_STORAGE_READ );
    if( !fileStorage )
    {
        fprintf(stderr, "Can't open facedata.xml\n");
        return 0;
    }

    nEigens = cvReadIntByName(fileStorage, 0, "nEigens", 0);
    nTrainFaces = cvReadIntByName(fileStorage, 0, "nTrainFaces", 0);
    *pTrainPersonNumMat = (CvMat *)cvReadByName(fileStorage, 0, "trainPersonNumMat", 0);
    eigenValMat  = (CvMat *)cvReadByName(fileStorage, 0, "eigenValMat", 0);
    projectedTrainFaceMat = (CvMat *)cvReadByName(fileStorage, 0, "projectedTrainFaceMat", 0);
    pAvgTrainImg = (IplImage *)cvReadByName(fileStorage, 0, "avgTrainImg", 0);
    eigenVectArr = (IplImage **)cvAlloc(nTrainFaces*sizeof(IplImage *));
    for(i=0; i<nEigens; i++)
    {
        char varname[200];
        sprintf_s( varname, "eigenVect_%d", i );
        eigenVectArr[i] = (IplImage *)cvReadByName(fileStorage, 0, varname, 0);
    }

    // release the file-storage interface
    cvReleaseFileStorage( &fileStorage );

    return 1;
}


//////////////////////////////////
// storeTrainingData()
//
void storeTrainingData()
{
    CvFileStorage * fileStorage;
    int i;

    // create a file-storage interface
    fileStorage = cvOpenFileStorage( "C:/Users/HP/Desktop/OpenCV/facedata.xml", 0, CV_STORAGE_WRITE );

    // store all the data
    cvWriteInt( fileStorage, "nEigens", nEigens );
    cvWriteInt( fileStorage, "nTrainFaces", nTrainFaces );
    cvWrite(fileStorage, "trainPersonNumMat", personNumTruthMat, cvAttrList(0,0));
    cvWrite(fileStorage, "eigenValMat", eigenValMat, cvAttrList(0,0));
    cvWrite(fileStorage, "projectedTrainFaceMat", projectedTrainFaceMat, cvAttrList(0,0));
    cvWrite(fileStorage, "avgTrainImg", pAvgTrainImg, cvAttrList(0,0));
    for(i=0; i<nEigens; i++)
    {
        char varname[200];
        sprintf( varname, "eigenVect_%d", i );
        cvWrite(fileStorage, varname, eigenVectArr[i], cvAttrList(0,0));
    }

    // release the file-storage interface
    cvReleaseFileStorage( &fileStorage );
}


//////////////////////////////////
// findNearestNeighbor()
//
int findNearestNeighbor(float * projectedTestFace)
{
    //double leastDistSq = 1e12;
    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];  // Mahalanobis
            distSq += d_i*d_i; // Euclidean
        }

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

    return iNearest;
}


//////////////////////////////////
// doPCA()
//
void doPCA()
{
    int i;
    CvTermCriteria calcLimit;
    CvSize faceImgSize;

    // set the number of eigenvalues to use
    nEigens = nTrainFaces-1;

    // allocate the eigenvector images
    faceImgSize.width  = faceImgArr[0]->width;
    faceImgSize.height = faceImgArr[0]->height;
    eigenVectArr = (IplImage**)cvAlloc(sizeof(IplImage*) * nEigens);
    for(i=0; i<nEigens; i++)
        eigenVectArr[i] = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);

    // allocate the eigenvalue array
    eigenValMat = cvCreateMat( 1, nEigens, CV_32FC1 );

    // allocate the averaged image
    pAvgTrainImg = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);

    // set the PCA termination criterion
    calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);

    // compute average image, eigenvalues, and eigenvectors
    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);
}


//////////////////////////////////
// loadFaceImgArray()
//
int loadFaceImgArray(char * filename)
{
    FILE * imgListFile = 0;
    char imgFilename[512];
    int iFace, nFaces=0;


    // open the input file
    if( !(imgListFile = fopen(filename, "r")) )
    {
        fprintf(stderr, "Can\'t open file %s\n", filename);
        return 0;
    }

    // count the number of faces
    while( fgets(imgFilename, 512, imgListFile) ) ++nFaces;
    rewind(imgListFile);

    // allocate the face-image array and person number matrix
    faceImgArr        = (IplImage **)cvAlloc( nFaces*sizeof(IplImage *) );
    personNumTruthMat = cvCreateMat( 1, nFaces, CV_32SC1 );

    // store the face images in an array
    for(iFace=0; iFace<nFaces; iFace++)
    {
        // read person number and name of image file
        fscanf(imgListFile,
            "%d %s", personNumTruthMat->data.i+iFace, imgFilename);

        // load the face image
        faceImgArr[iFace] = cvLoadImage(imgFilename, CV_LOAD_IMAGE_GRAYSCALE);

        if( !faceImgArr[iFace] )
        {
            fprintf(stderr, "Can\'t load image from %s\n", imgFilename);
            return 0;
        }
    }

    fclose(imgListFile);

    return nFaces;
}


//////////////////////////////////
// printUsage()
//
void printUsage()
{
    printf("Usage: eigenface <command>\n",
           "  Valid commands are\n"
           "    train\n"
           "    test\n");
}

1) 当我尝试执行程序时,程序以 Native' 退出并以代码 0 (0x0) 退出。为什么会这样?

需要一些帮助...谢谢...

最佳答案

首先,我会确保数据确实正确加载。其次确保您链接的是正确的 OpenCV 库。有些人有奇怪的错误(类似于你的错误),因为他们在没有调试符号的情况下链接到 OpenCV 构建时进行了调试构建。请查看我的教程中有关发布构建配置的部分:

我只是想让你知道我正在为 OpenCV 提供人脸识别库:

这个有特征脸、Fisher 脸和局部二进制模式直方图。而且:从 2.4 开始,该库也被合并到 OpenCV 中,因此每个 OpenCV 2.4+ 版本都附带了 Eigenfaces、Fisherfaces 和 Local Binary Patterns Histograms。 opencv/samples/cpp 文件夹中有演示应用程序,它随任何 OpenCV 安装一起提供:

我将在本周末上传 OpenCV 的文档并相应地更新这篇文章。

关于opencv - 在 OpenCV 上实现特征脸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9545393/

相关文章:

android-layout - 带有自定义布局的 opencv 实现(在 SurfaceView 上)

python - 如何将 RGBA 字节串转换为灰度图像?

python - Keras 检查输入 : expected input_4 to have shape (299, 299, 3) 时出错,但得到形状为 (64, 64, 3) 的数组

c++ - 如何使用 vlfeat 和 opencv 在 C++ 中确定图像的 PHOW 特征?

iphone - 从 UIImagePickerController SourceType 相机获取全高清图像,无需单击捕获按钮

c++ - 如何修复内存不足错误(openCV)

c++ - multimap 像拼接 - 添加第三个图像

python - pytorch dataloader RuntimeError : stack expects each tensor to be equal size, 但在条目 0 处得到 [224, 224] 并在条目 1 处得到 [224, 224, 3]

android - 如何在使用 Android 移动视觉库时处理单个相机帧

ios - 使用前置摄像头拍摄时未检测到人脸