如何只保存一次相同的面孔

时间:2014-03-03 09:26:57

标签: c++ opencv image-processing

我正在做一个关于监控摄像头的人脸检测项目。现在我正处于人脸检测的阶段,我可以检测到每个帧的脸部。检测到脸部后,我需要将脸部存储到本地文件夹。现在我可以保存指定文件夹中的每个面。

问题现在它正在保存每个面孔,但我只需要保存一次相同的面孔。这意味着如果将一个面部保存为jpeg图像,并且当面部检测再次进展时,同一面部即将到来,所以这次我不想保存那张特别的脸。

这是我的代码:

#include <cv.h>   
#include <highgui.h>
#include <time.h>
#include <stdio.h>
using namespace std;
int ct=1;
int ct1=0;
IplImage *frame;
int frames;
void facedetect(IplImage* image);
void saveImage(IplImage *img,char *ex);
IplImage* resizeImage(const IplImage *origImg, int newWidth,int newHeight, bool    keepAspectRatio);
const char* cascade_name="haarcascade_frontalface_default.xml";
int k=1;
int main(int argc, char** argv)
{
  CvCapture *capture=cvCaptureFromFile("Arnab Goswami on Pepper spary rajagopal        Complete NewsHour Debate (Mobile).3gp");
  int count=1;
  while(1)
  {
frame = cvQueryFrame(capture);
if(count%30==0)
{   
facedetect(frame);
}
count++;    
 }   
  cvReleaseCapture(&capture);
  return 0;
 }
void facedetect(IplImage* image)
{
    ct1++;
    cvNamedWindow("output");
int j=0,i,count=0,l=0,strsize;
char numstr[50];
int arr[100],arr1[100];
CvPoint ul,lr,w,h,ul1,lr1;
CvRect *r;
//int i=0;
IplImage* image1;IplImage* tmpsize;IplImage* reimg;
CvHaarClassifierCascade* cascade=(CvHaarClassifierCascade*) cvLoad(cascade_name);

CvMemStorage* storage=cvCreateMemStorage(0);
const char *extract;
if(!cascade)
{
    cout<<"Coulid not load classifier cascade"<<endl;

}
if(cascade)
{
          CvSeq*faces=cvHaarDetectObjects(image,cascade,storage,1.1,1,CV_HAAR_DO_CANNY_PRUNING,cvSize(10,10));
             //function used for detecting faces.o/p is list of detected faces.
    for(int i=0;i<(faces ? faces->total : 0);i++)
    {
        string s1="im",re,rename,ex=".jpeg";
        sprintf(numstr, "%d", k);
        re = s1 + numstr;
        rename=re+ex;
        char *extract1=new char[rename.size()+1];
        extract1[rename.size()]=0;
        memcpy(extract1,rename.c_str(),rename.size());
            //Copies the values of rename.size from the location pointed by source                                  //(rename.c_str)directly to the memory block pointed by destination(extract).
        strsize=rename.size();
        r=(CvRect*) cvGetSeqElem(faces,i);//draw rectangle outline around each image.
        ul.x=r->x;
        ul.y=r->y;
        w.x=r->width;
        h.y=r->height;
        lr.x=(r->x + r->width);
        lr.y=(r->y + r->height);
        cvSetImageROI(image,cvRect(ul.x,ul.y,w.x,h.y));
        image1=cvCreateImage(cvGetSize(image),image->depth,image->nChannels);
        cvCopy(image, image1, NULL);
        reimg=resizeImage(image1, 40, 40, true);
        saveImage(reimg,extract1);
        cvResetImageROI(image);
        cvRectangle(image,ul,lr,CV_RGB(1,255,0),3,8,0);
        j++,count++;
        k++;
        cout<<"frame"<<ct1<<" "<<"face"<<ct<<":"<<"x: "<<ul.x<<endl;
        cout<<"frame"<<ct1<<" "<<"face"<<ct<<":"<<"y: "<<ul.y<<endl;
        cout<<""<<endl;
        ct++;

        //cvShowImage("output",image);
    }

    //return image;
    //cvNamedWindow("output");//creating a window.
    cvShowImage("output",image);//showing resized image.
    cvWaitKey(0);

}

}
void saveImage(IplImage *img,char *ex)
{
    int i=0;
    char path[255]="/home/athira/Image/OutputImage";
    char *ext[200];
    char buff[1000];
    ext[i]=ex;
    sprintf(buff,"%s/%s",path,ext[i]);//copy ext[i] to buff
    strcat(path,buff);//concat path & buff
    cvSaveImage(buff,img);
    i++;
}

2 个答案:

答案 0 :(得分:0)

您正在使用基于haar功能的级联分类器进行对象检测。据我所知,这些xml文件只接受过基于数百张评估图片检测特定对象的培训(参见cascade classifier training)。

因此,为了比较保存的图像,您需要另一种“检测”模式,因为您必须比较两个面是否与视角相同等等(关键字:生物识别数据)。 您正在寻找的关键字是“face recognition”我认为。只需根据检测到的面部建立一个数据库,然后将其用于人脸识别。

修改 另一个可能有用的链接:www.shervinemami.info/faceRecognition.html

答案 1 :(得分:0)

如果我理解正确,你想要的是检测一帧中的脸部,保存这张脸的缩略图。然后,在下一帧中,您希望再次检测面部,但只保存第一帧中不存在的缩略图。

这个问题很难,因为视频中捕获的面孔总是从一帧变为另一帧。这是由于图像中的噪音,人们可能正在移动等等。因此,在监控录像中没有两张面孔相同

因此,为了实现您的要求,您需要确定您在考虑的面部是否已在之前的帧中观察过。在一般形式中,这个问题并不明显,并且仍然是许多与生物识别,行人跟踪和重新识别等相关的研究的主题。因此,你很难在检测到已经观察到给定面部时达到100%有效。

但是,如果可以接受不是100%有效的方法,您可以尝试以下方法:

  1. 检测第0帧中的面F 0 i ,并关联图像位置(x 0 i ,y 0 i ),并存储缩略图

  2. 计算位置上的稀疏光流(例如使用KLT,见this link)(x n-1 i ,y n-1 i )前一帧n-1中的面,以估计它们的位置(xx n i ,yy n i )当前帧n。

  3. 检测当前帧n中的面F 0 i ,并关联图像位置(x n i < / sub>,y n i ),并且只保存那些不接近预测位置之一的缩略图(xx n i ,yy n i )。

  4. 增加n并使用下一帧重复步骤2-3。

  5. 这是一种使用跟踪来确定先前是否已经观察过给定面部的简单算法。它应该比基于生物识别的方法更容易实现,并且在视频监控的背景下可能更合适。然而,由于光流估计和面部检测器的有效性有限, 100%准确,