jump to navigation

Code cài đặt giải thuật PCA – Code PCA 11/08/2013

Posted by hnb1988 in Tìm hiểu & chia sẽ.
Tags: , , , ,
trackback
Gửi các bạn,
Sau một thời gian dài lúc trước post bài viết tổng quan nhận dạng mặt người
Rất vui khi có rất nhiều bạn quan tâm tới về đề tài này. Và có nhiều bạn hỏi về code cài đặt.
Code này mình tìm hiểu cũng qua các link trên mạng, nhưng sợ bị mất mình mang về đây. Các bạn tham khảo bên dưới.
Trang tham khảo code link gốc (Nếu vẫn còn tồn tại, không thì xem code phía dưới nhé  ^^ ).
Cài đặt giải thuật PCA:

http://c.pastebin.com/z7YmnPLf

OpenCV: Finding Faces
http://www.cognotics.com/opencv/servo_2007_series/part_2/index.html

// eigenface.c, by Robin Hewitt, 2007
//
// Example program showing how to implement eigenface with OpenCV
// Usage:
//
// First, you need some face images. I used the ORL face database.
// You can download it for free at
//    www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
//
// List the training and test face images you want to use in the
// input files train.txt and test.txt. (Example input files are provided
// in the download.) To use these input files exactly as provided, unzip
// the ORL face database, and place train.txt, test.txt, and eigenface.exe
// at the root of the unzipped database.
//
// To run the learning phase of eigenface, enter
//    eigenface train
// at the command prompt. To run the recognition phase, enter
//    eigenface test
#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 )
{
        // 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(“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(“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( “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( 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( “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”);
}

Comments»

1. Thuy Quynh - 11/08/2013

Em có thể xin số điện thoại của anh để hỏi 1 chút được ko ạ. Cảm ơn anh rất nhiều!

Đã gửi từ iPhone của tôi

Ngày 11-08-2013, vào lúc 20:14, Blog IT & Life viết:

> >

hnb1988 - 13/08/2013

Mình đã gửi qua mail rồi nhé, check mail giúp mình


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: