上一篇:opencv人脸检测_cascade.detectMultiScale参数详解
不知道有没有帮助到大家,如果没有肯定是我没有讲的太清楚,那么我修改了下上篇,手把手写一下。
本篇是用MFC进界面编写,遇到些问题,很难受。
1.关于MFC
微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。
2.常用控件
Button
Picture Control
Static Text
Radio Butto
3.程序实现
其实我要实现的是打开文件中的人物图片且显示,然后点击检测图片后显示圈出人脸的图片再左边。
OpenImg控件的实现没有问题,如下。
代码如下:
void CfacedectectMFC2Dlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 //进度条置为零 //CProgressCtrl *prgs = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS); //prgs->SetPos(0); //选择图片 CFileDialog fileDlg(TRUE, _T("png"), NULL, 0, _T("image Files(*.bmp; *.jpg;*.png)|*.JPG;*.PNG;*.BMP|All Files (*.*) |*.*||"), this); fileDlg.DoModal(); //获取图片路径和图片名称 CString strFilePath = fileDlg.GetPathName(); /* printf("%s", strFilePath);*/ CString strFileName = fileDlg.GetFileName(); //判断路径不为空 if (strFilePath == _T("")) { return; } ATL::CImage image; image.Load(strFilePath); image.Save(_T("open.jpg")); //以下两个矩形主要作用是,获取对话框上面的Picture Control的width和height, //并设置到图片矩形rectPicture,根据图片矩形rectPicture对图片进行处理, //最后绘制图片到对话框上Picture Control上面 CRect rectControl; //控件矩形对象 CRect rectPicture; //图片矩形对象 int x = image.GetWidth(); int y = image.GetHeight(); //Picture Control的ID为IDC_open CWnd *pWnd = GetDlgItem(IDC_open2); pWnd->GetClientRect(rectControl); CDC *pDc = GetDlgItem(IDC_open2)->GetDC(); SetStretchBltMode(pDc->m_hDC, STRETCH_HALFTONE); rectPicture = CRect(rectControl.TopLeft(), CSize((int)rectControl.Width(), (int)rectControl.Height())); ((CStatic*)GetDlgItem(IDC_open2))->SetBitmap(NULL); //以下两种方法都可绘制图片 //image.StretchBlt(pDc->m_hDC, rectPicture, SRCCOPY); //将图片绘制到Picture控件表示的矩形区域 image.Draw(pDc->m_hDC, rectPicture); //将图片绘制到Picture控件表示的矩形区域 image.Destroy(); pWnd->ReleaseDC(pDc); }
是的,你想的没错,我就是用找到的图片利用 image.Save(_T("open.jpg")); 保存到本项目文件下,以便DetectImg控件去使用读入的图片。
其实我知道有点不好,但是我现在目前没有找到资料去定义全局变量,也就是将OpenImg控件读入的图片设置为全局变量Mat ,这样就可以给DetectImg控件使用了,然后检测人脸,然后而且可以直接在原图上圈出人脸,然后显示在右边窗口。
哎。。难受呀,没有找到资料,我还是第一次学习MFC,这算是第一个项目工程,MFC显示图片到窗口有很多种办法,三种吧,我可能用的是最古老的那种方法,所以还可以好好学习一下,应该是没有问题的。
void CfacedectectMFC2Dlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 ///////////////////////////////////// //// 这一段用于检测人脸,后期可 //// //// 自定义子函数,增加程序可读性 //// ///////////////////////////////////// //1.加载分类器 CascadeClassifier cascade; cascade.load("haarcascade_frontalface_alt2.xml"); // cascade.load("haarcascade_frontalface_default.xml"); Mat srcImg, dstImg, grayImg; CString strFilePath; //2.读取图片 srcImg = imread("open.jpg"); dstImg = srcImg.clone(); grayImg.create(srcImg.size(), srcImg.type()); cvtColor(srcImg, grayImg, CV_BGR2GRAY);//生成灰度图,提高检测效率 //定义7种颜色,用于标记人脸 Scalar colors[] = { //红橙黄绿青蓝紫 CV_RGB(255, 0, 0), CV_RGB(255, 97, 0), CV_RGB(255, 255, 0), CV_RGB(0, 255, 0), CV_RGB(0, 255, 255), CV_RGB(0, 0, 255), CV_RGB(160, 32, 240) }; //3.检测 vector<Rect> rect; cascade.detectMultiScale(grayImg, rect, 1.1, 3, 0);//分类器对象调用 // printf("检测到人脸个数:%d\n", rect.size()); //4.标记--在脸部画圆 for (int i = 0; i < rect.size(); i++) { Point center; int radius; center.x = cvRound((rect[i].x + rect[i].width * 0.5)); center.y = cvRound((rect[i].y + rect[i].height * 0.5)); radius = cvRound((rect[i].width + rect[i].height) * 0.25); circle(dstImg, center, radius, colors[i % 7], 2); } imwrite("after.jpg", dstImg); int cx, cy; ATL::CImage dstimage; CRect rect1; dstimage.Load(_T("after.jpg")); //获取图片的宽 高 cx = dstimage.GetWidth(); cy = dstimage.GetHeight(); CWnd *pWnd = NULL; pWnd = GetDlgItem(IDCLOSE);//获取控件句柄 //获取Picture Control控件的客户区 pWnd->GetClientRect(&rect1); CDC *pDc = NULL; pDc = pWnd->GetDC();//获取picture control的DC //设置指定设备环境中的位图拉伸模式 int ModeOld = SetStretchBltMode(pDc->m_hDC, STRETCH_HALFTONE); //从源矩形中复制一个位图到目标矩形,按目标设备设置的模式进行图像的拉伸或压缩 dstimage.StretchBlt(pDc->m_hDC, rect1, SRCCOPY); SetStretchBltMode(pDc->m_hDC, ModeOld); ReleaseDC(pDc); /*IplImage iplimg = dstImg;*/ //DrawPicToHDC(&iplimg, IDCLOSE); }
这里出现问题......
我想很快就可以解决了。。。。。