您的位置:首页 > 其它

mfc下的人脸检测并保存截图

2014-04-10 08:20 232 查看
上次写过了一个人脸检测并切分出人脸的例子,这次也是同一个东西,有点“换汤不换药”感觉。不过这次是在上次的基础上稍微进行了一些改进,因为上次那个代码最后显示灰度图像有些模糊不清和原始灰度图片色差比较大。上次的主要问题是在后面切分和保存的灰度图像都是用的resize后的那个图片,通过实验发现,resize后的图片确实改变了原图的清晰度。所以稍微改动了下detect函数,使最后保存和显示的都是原灰度图像。

1.建一个mfc应用程序,文件->新建->项目->vc++->mfc->mfc应用程序,然后根据导向在”应用程序类型“弹出的对话框中选择基于对话框。

2.往对话框中添加两个picture control控件和两个button如下:


3.添加打开文件按钮事件(双击按钮即可),这里我把按钮的ID属性改为了IDC_opencfile_BUTTON。代码:

void CmfcRecognitionDlg::OnBnClickedopencfileButton()
{
// TODO: 在此添加控件通知处理程序代码

CFileDialog dlg(TRUE, //TRUE为OPEN对话框,FALSE为SAVE AS对话框
NULL,
NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
(LPCTSTR)_TEXT("JPG Files (*.jpg)|*.jpg|All Files (*.*)|*.*||"),
NULL);

if(dlg.DoModal()==IDOK)
{
FilePathName=dlg.GetPathName(); //文件名保存在了FilePathName里
//AfxMessageBox(_T(FilePathName));
UpdateData(false); //更新路径公共变量
show_picture();
}
else
{
return;
}
}
在此先把要用到的变量先全放在该cpp文件开头,即作为全局变量
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
static char* cascade_name="haarcascade_frontalface_alt.xml";
static char* detect_face_file="detect.png";
CString FilePathName;
const double scale=2.0;
4.添加上面代码中用到的show_picture函数:
void CmfcRecognitionDlg::show_picture()
{
if(FilePathName=="")
{
return ;
}
CRect rect;
m_Pic.GetClientRect(&rect);     //m_picture为Picture Control控件变量,获得控件的区域对象

CImage image;       //使用图片类
image.Load(FilePathName);   //装载路径下图片信息到图片类
CDC* pDC = m_Pic.GetWindowDC();    //获得显示控件的DC
image.Draw( pDC -> m_hDC,rect);      //图片类的图片绘制Draw函数
ReleaseDC(pDC);

}
注意,此处该函数在头文件中要进行声明,上图左边的picture control的变量设为了m_Pic(选中该picturecontrol控件,右击选中添加变量)。

5.添加”检测人脸“按钮事件(ID改为了face_detect):

void CmfcRecognitionDlg::OnBnClickeddetect()
{
// TODO: 在此添加控件通知处理程序代码

//string file(FilePathName);
const char * filename =(LPSTR)(LPCTSTR)FilePathName;
IplImage* img = cvLoadImage(filename,1);
IplImage* grayImg=cvCreateImage(cvGetSize(img),img->depth,1);
IplImage* smallImg=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),IPL_DEPTH_8U,1);
cvCvtColor(img,grayImg,CV_BGR2GRAY);
cvResize(grayImg,smallImg,CV_INTER_LINEAR);
cvEqualizeHist(smallImg,smallImg);
detectFace(smallImg,grayImg);
CRect rect;
m_Detect_face.GetClientRect(&rect);     //m_picture为Picture Control控件变量,获得控件的区域对象
CImage image;       //使用图片类
image.Load("saveImg/0.png");   //装载路径下图片信息到图片类,注意,这里用的是0.png,当你的图片截出多张人脸是,在右边框显示的可能就不是你想要的。
CDC* pDC = m_Detect_face.GetWindowDC();    //获得显示控件的DC,同理这里对ID为face_detect的picture control控件添加了变量名为m_Detect_face
image.Draw( pDC -> m_hDC,rect);      //图片类的图片绘制Draw函数
ReleaseDC(pDC);
}

6.往该cpp文件对应的头文件(.h)中添加类成员函数int detectFace(IplImage* grayImg,IplImage* img),然后往该cpp中添加该函数体:

int CmfcRecognitionDlg::detectFace(IplImage* grayImg,IplImage* img){
//这里和之前一样要在当前路径下建一个saveImg文件夹
CString ss("saveImg/");static CvScalar colors[] = {         {{0,0,255}},{{0,128,255}},{{0,255,255}},{{0,255,0}},         {{255,128,0}},{{255,255,0}},{{255,0,0}},{{255,0,255}}     };cascade_name = "haarcascade_frontalface_alt2.xml"; storage = cvCreateMemStorage(0); cvClearMemStorage(storage);     cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );     if( !cascade )     { AfxMessageBox(_T("ERROR: Could not load classifier cascade\n"));        return -1;     }  CvSeq* objects = cvHaarDetectObjects(grayImg,  cascade,  storage, 1.1,2,                                                                         0/*CV_HAAR_DO_CANNY_PRUNING*/,                                                                         cvSize(30,30)); CvSize dst_cvsize; dst_cvsize.width=200; dst_cvsize.height=200; for(int i=0;i<(objects? objects->total:0);++i)     { char char2[3];itoa(i,char2,10);ss.Append(char2);ss.Append(".png");        CvRect* r=(CvRect*)cvGetSeqElem(objects,i); cvSetImageROI(img,cvRect(r->x*scale,r->y*scale,r->width*scale,r->height*scale));  IplImage* dst = cvCreateImage(cvSize(r->width*scale,r->height*scale),IPL_DEPTH_8U,1);    IplImage* fixed_dst=cvCreateImage(dst_cvsize,IPL_DEPTH_8U,1);cvCopy(img,dst,0);   cvResetImageROI(img);cvResize(dst,fixed_dst,CV_INTER_LINEAR);cvSaveImage((LPSTR)(LPCTSTR)ss,fixed_dst);        cvRectangle(img, cvPoint(r->x*scale,r->y*scale), cvPoint((r->x+r->width)*scale,(r->y+r->height)*scale), colors[i%8]); cvSaveImage(detect_face_file,img);cvReleaseImage(&dst);cvReleaseImage(&fixed_dst);ss.Empty();ss.Append("saveImg/");    }      return 1;}

通过该函数可以看出,这个函数是在之前函数的基础上进行了一些改进,把多余的temp去掉了,并且使用的是原灰度图像进行截取并保存的。所以就不会出现之前的那种截出图像比较模糊的现象。

在头文件头部添加:
#include <cstring>
#include "highgui.h"
#include <cv.h>
#include <cvaux.h>
#pragma comment(lib, "opencv_objdetect248d.lib")


最后效果如下(由于框的大小和图片不一样,造成图片被挤压了,看起来不怎么好看,可以处理下):

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: