关闭

C++开发人脸性别识别教程(9)——搭建MFC框架之显示图片

标签: mfcCvvImage
8006人阅读 评论(26) 收藏 举报
分类:

  在之前的博客中我们已经实现读取用户选定的文件夹,并将其路径保存在相应的变量中,在这篇博文中我们将介绍如何借助CvvImage类将图片显示在picture控件中,并自动读取文件夹下的其他图片。

  一、添加“下一张”按钮

  由于我们需要读取文件夹下的所有图像文件,而非某一张文件,因此有必要添加一个按钮来进行控制,具体功能就是:每单击一次这个按钮,程序就会自动读取下一张图片并显示在界面上。由于之前已经详细介绍了MFC中添加Button控件的方式,这里不再赘述。添加一个按钮,命名为“下一张”,将ID更改为IDC_BUTTON_NextImage:

  二、编写遍历函数

  在上一篇博客中我们提到,在选中文件夹之后,程序会将文件夹的路径保存在m_Path变量之中。接下来我们就借助这个变量来进一步遍历其路径下的图像文件。这里我们专门编写一个函数来实现“遍历下一张图片”的功能,命名为GetNextBigImg。因此,需要向CGenderRecognitionMFCDlg类中添加这个成员函数。在类视图中右击相应的类,在快捷菜单中选择“添加->添加函数”,输入函数的属性:

  GetNextBigImg()函数主要承担着一下几个任务:

  1、开始遍历

  这里将GetNextBigImg()放在OnBnClickedButtonImagefile()函数中的末尾部分进行调用,用以在单击“图片文件夹”按钮读取文件夹信息之后启用文件读取程序。

  2、从当前目录路径下读入一个文件

  这里读取文件主要通过readdir函数来完成,考虑到用户可能会选择一个空文件夹,因此这里需要对读取操作进行一次判断:

    if (m_pDir && (m_pEnt = readdir(m_pDir)) != NULL)
    {

    }

  readdir()函数能够实现对当前目录结构(m_pDir)中的文件的无重复顺序读取,即每次读取完成后都会自动移到下一个待读取的文件,与指针的机制类似,readdir()函数包含在dirent.h头文件中,之前已经添加并包含完毕。此时,m_pEnt变量中保存了文件名称:

  3、判断是否为图像文件

  这里采用strstr()函数来判断文件名中是否包含对应的扩展名字符串,这里默认的图像格式有四种:jpg ,bmp,png:

    if (m_pDir && (m_pEnt = readdir(m_pDir)) != NULL)
    {
        /**********判断是否为图像文件**********/
        char* jpg = strstr(m_pEnt->d_name,".jpg");
        char* bmp = strstr(m_pEnt->d_name,".bmp");
        char* png = strstr(m_pEnt->d_name,".png");
    }

  至于“m_pEnt->d_name”这种调用格式,在dirent.h头文件中有着明确定义,有疑问的话可以查阅相关文件。接下里通过判断jpg、bmp、png这几个变量是否为空来确定文件是否是图像文件:

    if (m_pDir && (m_pEnt = readdir(m_pDir)) != NULL)
    {
        /**********判断是否为图像文件**********/
        char* jpg = strstr(m_pEnt->d_name,".jpg");
        char* bmp = strstr(m_pEnt->d_name,".bmp");
        char* png = strstr(m_pEnt->d_name,".png");

        if (jpg == NULL && bmp == NULL && png == NULL)      //如果该文件不是图像文件
        {
            GetNextBigImg();
        }
        else
        {
            /**********显示该图片**********/
        }
    }

  注意这里采用了一种递归的方式来实现非图像文件的轮询,即当前文件被判定为非图像文件时(jpg、bmp、png均为空),则调用自身GetNextBigImg(),也就意味着再次执行一遍readdir()函数,使得文件指针后移意味,层层递归实现最终的文件遍历;相应的,如果当前文件为三种图像文件中的一种,则将当前图片绘制到picture控件中,接下来编写绘制图像的代码。

  4、绘制图像至picture控件

  此时该轮到CvvImage大显身手了。在此之前,我们需要先为picture控件关联一个CRect类型的矩形变量,这个变量将用来保存picture控件在客户区所处的位置。首先,为CGenderRecognitionMFCDlg类添加成员变量m_PicCtlRect:

  然后,再添加一个HDC(句柄)变量m_pPicCtlHdc,用于保存控件的句柄:

   然后在CGenderRecognitionMFCDlg的对话框初始化函数OnInitDialog()中编写两行代码,将控件、句柄、位置信息这三个变量相互关联起来:

    /*********初始化picture控件**********/
    m_pPicCtlHdc = GetDlgItem(IDC_PICTURE)->GetDC()->GetSafeHdc();   //返回控件句柄
    GetDlgItem(IDC_PICTURE)->GetClientRect(m_PicCtlRect);            //关联控件位置

  将这两句代码添加到OnInitDialog()末尾即可,这里有三个问题需要强调:

  (1)为什么需要用到句柄和CRect变量?原因很简单,CvvImage类的要求。这里我们介绍一个查看函数形参的小技巧,即在函数名的括号中输入一个逗号,VS就会自动给出函数的形参格式:

  可见,DrawToHDC这个函数需要两个参数,一个是HDC类型的,一个是RECT*类型的。

  (2)如何快速查找类的成员函数?最直接的方法就是通过类视图,单击对应的类来进行浏览即可:

  当然,通过上方的搜索栏也是可以的。

  (3)OnInitDialog函数。这个函数在程序开始构造MFC框架时执行,因此有关控件的初始化操作都应该在这个函数中进行,而非构造函数。

  此时准备工作已经完成,可以为GetNextBigImg()函数添加正式的显示代码了:

            /**********显示该图片**********/
            IplImage* imageSrc;
            CvvImage imageSrcCvvImg;
            char imageFullName [500];                  //保存图像文件的全路径

            sprintf_s(imageFullName,"%s%s",m_ImageDir,m_pEnt->d_name);  //拼出文件全路径
            imageSrc = cvLoadImage(imageFullName);
            imageSrcCvvImg.CopyOf(imageSrc);
            imageSrcCvvImg.DrawToHDC(m_pPicCtlHdc,m_PicCtlRect);
            cvReleaseImage(&imageSrc);

  此时,运行程序,通过“图像文件夹按钮”,选择一个含有图片文件的文件夹,程序正常显示图片:

  5、添加“下一张”功能

  接下来我们为界面中的“下一张”按钮指定其功能。双击“下一张”按钮,添加响应函数:

  由于之前我们已经将图片轮询、显示操作封装在了GetNextBigImg()函数中,在这里我们只需调用一把这个函数即可实现“下一张”的功能:

void CGenderRecognitionMFCDlg::OnBnClickedButtonNextimage()
{
    GetNextBigImg();
    // TODO: 在此添加控件通知处理程序代码
}

  OK,大功告成。 

  三、总结

  经过这篇博文,我们的MFC框架已经具备了基本的图像显示功能,在下一篇博文中我们将向其中添加人脸检测的功能。这里有几个问题需要注意。

  1、OpenCv2.x关于图片显示的问题

  大家留心观察会发现,这里用到的CvvImage方法是完全基于OpenCv1.x的,用IplImage变量来表示图片。

  2、递归层数的问题

  这里GetNextBigImg()函数存在一个递归调用的过程,存在递归就需要考虑递归深度的问题。这里每遍历到一个非图像文件,递归的深度就增加一层,如果超过规定的递归深度,程序就会崩溃,从这个角度来讲通过递归的方法来轮询图像文件和非图像文件,是存在严重BUG隐患的,只要文件夹下有足够多的非图像文件,程序必然会因为无限递归而崩溃,相信大家有能力找到其他更安全的方法来解决这个问题。

7
5
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

MFC中利用Opencv与C++抓取摄像头进行人脸识别(Mat)

第一次写博客哈哈,有些小激动,还请各位大神多多包涵~ 最近的项目需要用到人脸识别,作为一个车辆工程的二年级本科生是崩溃的(一是没有很好的编程基础,只会编一下C与C#;二是…我是车辆工程的啊喂…...
  • Mr_Curry
  • Mr_Curry
  • 2016-04-08 17:27
  • 9584

C++开发人脸性别识别教程(10)——添加图片的人脸检测程序

如今我们的MFC框架已经初具规模,能够读取并显示文件夹下的图片,在这篇博文中我们将向其中添加人脸检测的程序。  一、人脸检测算法  这里我们使用OpenCv封装的Adaboost方法来进行人脸检测,参...
  • u013088062
  • u013088062
  • 2016-01-12 22:06
  • 4686

C++开发人脸性别识别教程(7)——搭建MFC框架之界面绘制

在之前的博客中我们已经将项目中用到的算法表述完毕,包括人脸检测算法以及四种性别识别算法,在这篇博客中我们将着手搭建基本的MFC框架。   一、框架概况   在这篇博文中我们将搭建最基本的M...
  • u013088062
  • u013088062
  • 2016-01-08 19:43
  • 4813

C++开发人脸性别识别教程(15)——搭建MFC框架启动摄像头

在之前的博文中已经完成了针对图片的人脸性别识别功能,在这篇文章中我们开始引入摄像头设备,为程序添加第二个功能:视频人脸性别识别。  一、添加控件  这里需要新添加两个与视频人脸性别识别相关的功能控件,...
  • u013088062
  • u013088062
  • 2016-02-27 09:19
  • 3685

C++开发人脸性别识别教程(8)——搭建MFC框架之读取文件夹信息

在上一篇博客中我们已经绘制了MFC界面,在这篇博客中我们将添加响应代码,为MFC框架添加一个最基本的功能:打开一个文件夹。   一、添加相关头文件   这里头文件主要包含三类:opencv...
  • u013088062
  • u013088062
  • 2016-01-09 12:50
  • 5888

C++开发人脸性别识别教程(11)——图片人脸检测程序BUG处理

在这篇博客需要解决之前遗留的两个BUG,一是用户在不初始化条件下运行程序,二是人脸检测的误差结果。  一、添加初始化警告  目前我们在“初始化”按钮对应的响应函数中封装了人脸分类器加载、开辟内存等操作...
  • u013088062
  • u013088062
  • 2016-01-13 22:02
  • 3097

C++开发人脸性别识别教程(10)——添加图片的人脸检测程序

如今我们的MFC框架已经初具规模,能够读取并显示文件夹下的图片,在这篇博文中我们将向其中添加人脸检测的程序。  一、人脸检测算法  这里我们使用OpenCv封装的Adaboost方法来进行人脸检测,参...
  • u013088062
  • u013088062
  • 2016-01-12 22:06
  • 4686

C++开发人脸性别识别教程(1)——前瞻

大四暑假的时候,帮老师指导了一个本科大学生创新实验,主要目标是通过图像处理相关技术对人脸美丽度进行分类。其中一个很重要的环节就是人脸的性别识别,这里将这个部分单独拿出来,借住OpenCv这个开源的图像...
  • u013088062
  • u013088062
  • 2015-12-30 11:15
  • 9500

C++开发人脸性别识别教程(18)——辅助功能之文件名批量修改、方法验证

时光推移了30多天,这个人脸性别识别的小项目也接近尾声了,预计再通过三篇博文的篇幅来完成这个项目的收尾工作。在这篇博文中我们再为程序添加另外两个小的辅助功能:文件名批量修改、方法验证。  一 文件名批...
  • u013088062
  • u013088062
  • 2016-02-29 20:16
  • 3144

C++开发人脸性别识别教程(14)——灰度图像识别BUG处理

在这篇博客中,我们对目前程序中一个隐藏很深的BUG进行处理,这个BUG导致程序目前有一部分逻辑出现错误(虽然没有表现出来)。  一、触发BUG  1、准备触发样本  为了复现这个隐藏的BUG,需要实现...
  • u013088062
  • u013088062
  • 2016-01-20 21:27
  • 3615
    个人简介
    燕山大学研究生,目前研三。邮箱:1095988845@qq.com,交流请发邮件,评论和私信可能无法及时回复,谢谢。
    个人资料
    • 访问:1492972次
    • 积分:11107
    • 等级:
    • 排名:第1668名
    • 原创:134篇
    • 转载:2篇
    • 译文:0篇
    • 评论:550条
    博客专栏
    最新评论