如何只保存一次相同的面

how to save identical faces only once

本文关键字:一次 保存      更新时间:2023-10-16

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

问题现在它正在保存每个面,但我只需要保存一次相同的面。这意味着,如果将一张人脸保存为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++;
}

您正在使用基于haar特征的级联分类器进行对象检测。据我所知,这些xml文件只被训练来检测基于数百张评估图片的特定对象(请参阅级联分类器训练)。

因此,要比较保存的图像,您需要另一种"检测"模式,因为您必须比较两张脸在视角等方面是否相同(关键词:生物特征数据)。我想你要找的关键词是"人脸识别"。只需根据检测到的人脸建立一个数据库,然后将其用于人脸识别。

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

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

这个问题很难解决,因为视频中捕捉到的人脸总是从一帧变到下一帧。这是由于图像中的噪声、人员可能在移动等原因造成的。因此,监控视频中没有两张脸是相同的。

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

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

  1. 检测帧0中的人脸F0i,以及相关的图像位置(x0i、y0i),并存储缩略图

  2. 计算前一帧n-1中人脸的位置(xn-1i,yn-1i

  3. 检测当前帧n中的人脸F0i以及相关联的图像位置(xn>i,yn<1sub>i),并且仅保存那些不靠近预测位置之一的人脸的缩略图(xxn-<2sub>iyyyyn

  4. 递增n,然后使用下一帧重复步骤2-3。

这是一个简单的算法,使用跟踪来确定之前是否已经观察到给定的人脸。它应该比基于生物特征的方法更容易实现,而且可能更适合视频监控。然而,由于光流估计和人脸检测器的有效性有限,不是100%准确的