2012-02-29 25 views
2

私はウェブカメラを使用してオンラインで顔認識を実装しようとしています。 6つのステップがあり、顔認識でOpenCVを使用したオンライン顔認識

  1. は、カメラからフレームをつかむ私は、私はいくつかの質問を持っている参照

    shervinemami.co.cc
    cognotics.com

    として、この2つのウェブサイトを使用しています

  2. 画像内の顔を検出する
  3. 画像
  4. は、画像内の人物を認識
  5. をプリプロセスをグレースケールにフレームを変換するだけで顔
  6. を表示するフレームをトリミング。

私は最初の5つのステップを実行できます。最後のステップはできません。ステップ5をステップ6にリンクする方法がわかりません。

私はトレーニングとテストの画像の情報を含むtrain.txtファイルとtest.txtファイルを作成しました。私はすでにlearn()、doPCA()のような関数をコードに追加しています...

しかし、ポイントは、すでに前処理された画像を認識するためにこれらの関数をメインでどのように使うかです。

は、以下のコード添付...それにいくつかの助けが必要:私はちょうどあなたのコードの

int _tmain(int argc, _TCHAR* argv[]) 
{ 
....... 
} 

部分を読ん

// 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; 
} 
+3

あなたはかなり曖昧な質問をしています。「ステップ5をステップ6にリンクするのが難しい」と尋ね、多くのコードを投稿しました。良い答えを得るチャンスを増やすには、顔を認識するために使用しようとしている方法を説明した後で、コードの関連するセクションだけを投稿することを検討してください。 – Chris

答えて

0

を。このコードは、画像内の顔を検出するために使用されます。それはFace_xと言います。今度はFace_xからフィーチャーを抽出し、それをF_xと呼んでください。あなたのデータベースでは、n異なる顔{Face_1, Face_2,..Face_N}から抽出された機能{F_1, F_2,..., F_N}を保存する必要があります。

Face_xを認識する単純なアルゴリズムは、F_xnの間のユークリッド距離を計算することです。最小距離(閾値以下)は、対応する面を与える。最小距離が閾値以下でない場合、Face_xは新しい顔です。機能F_xをデータベースに追加します。この方法でデータベースを増やすことができます。あなたは、データベースに機能を持たずにアルゴリズムを始めることができます。新しい顔ごとに、データベースが成長します。
私は

0

私の答えが遅れて来たかもしれないが、私はit.Iが同様のプロジェクトに取り組んでいると私は同じ問題に直面している答えるならば、それは仲間のために役に立つかもしれない、私が提案する方法は、ソリューションにあなたを導くことを願っていますそれを解決するには、コンピュータのハードディスク(CvWriteを使用)に保存された画像を保存したり書き込んだりすることで解決しました。保存された画像のパラメータをコードの認識部分に渡します。それは私の人生を楽にしてくれました。関心領域の矩形のパラメータを渡すことは私にとって少し難しかったです。あなたや他の誰かがこれを行った場合、私たちとコードを共有するのはすばらしいことでしょう。 次のコードを使用して、イメージをresizeimage関数を使用して定数値にサイズ変更した後に保存できます。この後

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

} 

あなたは

 Mat IplToMatConverter(IplImage* imageToMat) 
    { 
    Mat mat = cvarrToMat(imageToMat); 
    return mat; 
    } 

を使用してマットとちょうど他/難しい方法を行うFaceRecognizer API.Orにマットを使用するIplImageへ*を変更することができます。 ありがとう

関連する問題