首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于OpenCV的在线人脸识别

基于OpenCV的在线人脸识别
EN

Stack Overflow用户
提问于 2012-02-29 17:57:35
回答 2查看 4.7K关注 0票数 2

我正在尝试使用网络摄像头实现在线人脸识别。我用这两个网站作为参考。

shervinemami.co.cc

cognotics.com

我有几个问题:

在人脸识别方面,有6个步骤:

  1. 从相机里拿出一个框架
  2. 检测图像中的一张脸
  3. 裁剪帧,使之只露出脸。
  4. 将框架转换为灰度
  5. 图像预处理
  6. 识别图像中的人。

我能做前五步。最后一步我做不到。我不知道如何将步骤5连接到步骤6。

我已经创建了train.txt文件和test.txt文件,其中包含了培训和测试图像的信息。我已经将诸如learn()、doPCA()之类的函数添加到代码中.

但关键是如何主要使用这些函数来识别已经预处理的图像。

需要帮忙..。

随函附上以下代码:

代码语言:javascript
复制
// Real-time.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>

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


IplImage* getCameraFrame(CvCapture* &camera);
IplImage* detectFaces( IplImage *img ,CvHaarClassifierCascade* facecascade,CvMemStorage* storage );
CvRect detectFaceInImage(IplImage *inputImg, CvHaarClassifierCascade* cascade);
IplImage* preprocess( IplImage* inputImg);
IplImage* resizeImage(const IplImage *origImg, int newWidth,
    int newHeight, bool keepAspectRatio);
void learn();
void recognize();
void doPCA();
void storeTrainingData();
int  loadTrainingData(CvMat ** pTrainPersonNumMat);
int  findNearestNeighbor(float * projectedTestFace);
int  loadFaceImgArray(char * filename);

int _tmain(int argc, _TCHAR* argv[])
{
    CvCapture* camera = 0;  // The camera device.
    CvMemStorage            *storage;
    cvNamedWindow( "Realtime:", CV_WINDOW_AUTOSIZE);
    char *faceCascadeFilename = "C:/OpenCV2.1/data/haarcascades/haarcascade_frontalface_alt.xml";
    CvHaarClassifierCascade* faceCascade;
    faceCascade = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
    storage = cvCreateMemStorage( 0 );

    learn();

    while ( cvWaitKey(10) != 27 )   // Quit on "Escape" key
        {   
        IplImage *frame = getCameraFrame(camera);
        //IplImage* resized=cvCreateImage(cvSize(420,240),frame->depth,3);
        //cvResizeWindow( "Image:", 640, 480);
        //cvResize(frame,resized);
        //cvShowImage( "Realtime:", resized );
        IplImage *imgA = resizeImage(frame, 420,240, true);
        IplImage *frame1 = detectFaces(imgA,faceCascade,storage);
        frame1 = preprocess(frame1);
        }   
    // Free the camera.
    cvReleaseCapture( &camera );
    cvReleaseMemStorage( &storage );
    return 0;
}

IplImage* getCameraFrame(CvCapture* &camera)
{
    IplImage *frame;
    int w, h;

    // If the camera hasn't been initialized, then open it.
    if (!camera) {
        printf("Acessing the camera ...\n");
        camera = cvCreateCameraCapture( 0 );
        if (!camera) {
            printf("Couldn't access the camera.\n");
            exit(1);
        }
        // Try to set the camera resolution to 320 x 240.
        cvSetCaptureProperty(camera, CV_CAP_PROP_FRAME_WIDTH, 320);
        cvSetCaptureProperty(camera, CV_CAP_PROP_FRAME_HEIGHT, 240);
        // Get the first frame, to make sure the camera is initialized.
        frame = cvQueryFrame( camera );
        if (frame) {
            w = frame->width;
            h = frame->height;
            printf("Got the camera at %dx%d resolution.\n", w, h);
        }
        // Wait a little, so that the camera can auto-adjust its brightness.
        Sleep(1000);    // (in milliseconds)
    }

    // Wait until the next camera frame is ready, then grab it.
    frame = cvQueryFrame( camera );
    if (!frame) {
        printf("Couldn't grab a camera frame.\n");
        exit(1);
    }
    return frame;
}

CvRect detectFaceInImage(IplImage *inputImg, CvHaarClassifierCascade* cascade)
{
    // Smallest face size.
    CvSize minFeatureSize = cvSize(20, 20);
    // Only search for 1 face.
    int flags = CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_DO_ROUGH_SEARCH;
    // How detailed should the search be.
    float search_scale_factor = 1.1f;
    IplImage *detectImg;
    IplImage *greyImg = 0;
    CvMemStorage* storage;
    CvRect rc;
    double t;
    CvSeq* rects;
    CvSize size;
    int i, ms, nFaces;

    storage = cvCreateMemStorage(0);
    cvClearMemStorage( storage );


    // If the image is color, use a greyscale copy of the image.
    detectImg = (IplImage*)inputImg;
    if (inputImg->nChannels > 1) {
        size = cvSize(inputImg->width, inputImg->height);
        greyImg = cvCreateImage(size, IPL_DEPTH_8U, 1 );
        cvCvtColor( inputImg, greyImg, CV_BGR2GRAY );
        detectImg = greyImg;    // Use the greyscale image.
    }

    // Detect all the faces in the greyscale image.
    t = (double)cvGetTickCount();
    rects = cvHaarDetectObjects( detectImg, cascade, storage,
            search_scale_factor, 3, flags, minFeatureSize);
    t = (double)cvGetTickCount() - t;
    ms = cvRound( t / ((double)cvGetTickFrequency() * 1000.0) );
    nFaces = rects->total;
    printf("Face Detection took %d ms and found %d objects\n", ms, nFaces);

    // Get the first detected face (the biggest).
    if (nFaces > 0)
        rc = *(CvRect*)cvGetSeqElem( rects, 0 );
    else
        rc = cvRect(-1,-1,-1,-1);   // Couldn't find the face.

    if (greyImg)
        cvReleaseImage( &greyImg );
    cvReleaseMemStorage( &storage );
    //cvReleaseHaarClassifierCascade( &cascade );

    return rc;  // Return the biggest face found, or (-1,-1,-1,-1).
}

IplImage* detectFaces( IplImage *img ,CvHaarClassifierCascade* facecascade,CvMemStorage* storage )
{
    int i;
    CvRect *r;
    CvSeq *faces = cvHaarDetectObjects(
            img,
            facecascade,
            storage,
            1.1,
            3,
            0 /*CV_HAAR_DO_CANNY_PRUNNING*/,
            cvSize( 40, 40 ) );

    int padding_width = 30; // pixels
    int padding_height = 30; // pixels

    for( i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ ) {
        r = ( CvRect* )cvGetSeqElem( faces, i );
        cvRectangle( img,
                     cvPoint( r->x, r->y ),
                     cvPoint( r->x + r->width, r->y + r->height ),
                     CV_RGB( 255, 0, 0 ), 1, 8, 0 );
    }

    cvShowImage( "Realtime:", img );

    //cropping the face
    cvSetImageROI(img, cvRect(r->x,r->y,r->width,r->height));
    IplImage *img2 = cvCreateImage(cvGetSize(img), 
                            img->depth, 
                              img->nChannels);
    cvCopy(img, img2, NULL);
    cvResetImageROI(img);

    return img;
}

IplImage* preprocess( IplImage* inputImg){
    IplImage *detectImg, *greyImg = 0;
    IplImage *imageProcessed;
    CvSize size;
    detectImg = (IplImage*)inputImg;
    if (inputImg->nChannels > 1) {
        size = cvSize(inputImg->width, inputImg->height);
        greyImg = cvCreateImage(size, IPL_DEPTH_8U, 1 );
        cvCvtColor( inputImg, greyImg, CV_BGR2GRAY );
        detectImg = greyImg;    // Use the greyscale image.
    }

    imageProcessed = cvCreateImage(cvSize(inputImg->width, inputImg->height), IPL_DEPTH_8U, 1);
    cvResize(detectImg, imageProcessed, CV_INTER_LINEAR);
    cvEqualizeHist(imageProcessed, imageProcessed);
    return imageProcessed;
}

IplImage* resizeImage(const IplImage *origImg, int newWidth,
    int newHeight, bool keepAspectRatio)
{
    IplImage *outImg = 0;
    int origWidth;
    int origHeight;
    if (origImg) {
        origWidth = origImg->width;
        origHeight = origImg->height;
    }
    if (newWidth <= 0 || newHeight <= 0 || origImg == 0
        || origWidth <= 0 || origHeight <= 0) {
        //cerr << "ERROR: Bad desired image size of " << newWidth
        //  << "x" << newHeight << " in resizeImage().\n";
        exit(1);
    }

    if (keepAspectRatio) {
        // Resize the image without changing its aspect ratio,
        // by cropping off the edges and enlarging the middle section.
        CvRect r;
        // input aspect ratio
        float origAspect = (origWidth / (float)origHeight);
        // output aspect ratio
        float newAspect = (newWidth / (float)newHeight);
        // crop width to be origHeight * newAspect
        if (origAspect > newAspect) {
            int tw = (origHeight * newWidth) / newHeight;
            r = cvRect((origWidth - tw)/2, 0, tw, origHeight);
        }
        else {  // crop height to be origWidth / newAspect
            int th = (origWidth * newHeight) / newWidth;
            r = cvRect(0, (origHeight - th)/2, origWidth, th);
        }
        IplImage *croppedImg = cropImage(origImg, r);

        // Call this function again, with the new aspect ratio image.
        // Will do a scaled image resize with the correct aspect ratio.
        outImg = resizeImage(croppedImg, newWidth, newHeight, false);
        cvReleaseImage( &croppedImg );

    }
    else {

        // Scale the image to the new dimensions,
        // even if the aspect ratio will be changed.
        outImg = cvCreateImage(cvSize(newWidth, newHeight),
            origImg->depth, origImg->nChannels);
        if (newWidth > origImg->width && newHeight > origImg->height) {
            // Make the image larger
            cvResetImageROI((IplImage*)origImg);
            // CV_INTER_LINEAR: good at enlarging.
            // CV_INTER_CUBIC: good at enlarging.           
            cvResize(origImg, outImg, CV_INTER_LINEAR);
        }
        else {
            // Make the image smaller
            cvResetImageROI((IplImage*)origImg);
            // CV_INTER_AREA: good at shrinking (decimation) only.
            cvResize(origImg, outImg, CV_INTER_AREA);
        }

    }
    return outImg;
}

void learn()
{
    int i, offset;

    // load training data
    nTrainFaces = loadFaceImgArray("C:/Users/HP/Desktop/OpenCV/50_images_of_15_people.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();
}

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);
    }
}

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;
}

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 );
}

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;
}

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);
}

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;
}
EN

回答 2

Stack Overflow用户

发布于 2012-03-03 21:56:12

我刚读到

代码语言:javascript
复制
int _tmain(int argc, _TCHAR* argv[]) 
{
.......
}

是你代码的一部分。此代码用于检测图像中的面部。让我们说它是Face_x。现在从Face_x中提取特性,称之为F_x。在数据库中,您应该存储从{F_1, F_2,..., F_N}不同脸谱{Face_1, Face_2,..Face_N}中提取的特性{Face_1, Face_2,..Face_N}

识别Face_x的简单算法是计算F_xn特征之间的欧几里德距离。最小距离(低于阈值)给出相应的脸。如果最小距离不低于阈值,则Face_x是一个新面孔。向数据库中添加功能F_x。这样您就可以增加数据库。您可以在数据库中没有任何功能的情况下开始您的算法。随着每一张新面孔,数据库都在增长。

我希望我建议的方法能帮你找到解决办法。

票数 0
EN

Stack Overflow用户

发布于 2013-04-27 10:34:33

我的回答可能晚了,但如果我回答的话,可能对朋友有用。我正在做一个类似的项目,我也面临着同样的问题。我通过编写一个函数,将检测到的、裁剪的和预处理的图像保存或写入到我的计算机的硬盘上(使用CvWrite).And,将保存的图像的参数输入到代码的识别部分,从而解决了这个问题。这让我的生活变得更加艰难,easier.It让我更难通过感兴趣区域的参数。如果你或其他人这样做了,这可能是很好的分享代码与我们。可以使用代码上的resizeimage函数将图像大小调整为常值后,使用下面的代码保存图像。

代码语言:javascript
复制
    void saveCroppedFaces(CvSeq* tempon,IplImage* DetectedImage)
{

        char* name;
        int nFaces;
        CvRect rect;
        nFaces=tempon->total;
        name =new char[nFaces];
        IplImage* cropped = 0;
        IplImage* croppedResized=0;
        Mat croped;
        for(int k=0;k<nFaces;k++)
        {
            itoa(k,(name+k),10);
            rect = *(CvRect*)cvGetSeqElem( tempon, k );
            cropped= cropImage(DetectedImage,rect);
            //i can resize the cropped faces in to a fixed size here

            //i can write a function to save images and call it so
                  //that it will save it in to hard drive 
            //cvNamedWindow((name+k),CV_WINDOW_AUTOSIZE);

            //cvShowImage((name+k),cropped);
            croppedResized=resizeImage(cropped,60,60);
            croped=IplToMatConverter(croppedResized);
            saveROI(croped,itoa(k,(name+k),10));
            cvReleaseImage(&cropped);
        }
    name=NULL;
    delete[] name;

}

void saveROI(Mat mat,String outputFileName)
{
    string store_path("C://Users/sizusuzu/Desktop/Images/FaceDetection2
                                                    /"+outputFileName+".jpg");
    bool write_success = imwrite(store_path,mat);

}

之后,可以使用以下方法将IplImage*更改为Mat

代码语言:javascript
复制
      Mat IplToMatConverter(IplImage* imageToMat)
     {
    Mat mat = cvarrToMat(imageToMat);
    return mat;
     }

在FaceRecognizer API.Or中使用Mat,只需做另一种/更难的方式。谢谢

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9504216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档