数字图像处理与机器视觉:Visual C++与Matlab实现(第2版)
上QQ阅读APP看书,第一时间看更新

2.5 CImg应用示例

本节提供一个使用示例程序DIPDemo进行简单图像处理操作的范例,对一张示例图像进行简单的清空操作(置白)。这可以通过以参数255调用CImg类中的图像数据初始化方法InitPixels()来实现。读者在阅读过程中,除注意程序框架结构的基本使用方法外,还应对2.5.3小节InitPixels()函数基于逐行扫描像素的图像处理算法的实现方式建立一个基本的认识。

2.5.1 打开图像

可以通过菜单命令“文件→打开”来打开需要清空的图像,如图2.4所示。

文档类的OnOpenDocument()方法用于响应打开文件的菜单消息,该方法调用了CImg的图像文件读取方法AttachFromFile()。下面给出OnOpenDocument()方法的实现代码。

图2.4 打开文件

      BOOL CDIPDemoDoc::OnOpenDocument(LPCTSTR lpszPathName)
      {
            DeleteContents();

            // 更改光标形状
            BeginWaitCursor();

            // 读取图像并附加到m_Image上
            if(! m_Image.AttachFromFile(lpszPathName))
            {
                EndWaitCursor();
                AfxMessageBox("打开文件时出错!请确保正确的位图(*.bmp)文件类型。");
                return FALSE;
            }

            // 恢复光标形状
            EndWaitCursor();

            // 判断读取成功否
            if (! m_Image.m_lpData)
            {
                // 失败,可能非BMP格式
                CString strMsg;
                strMsg = "读取图像时出错!可能是不支持该类型的图像文件!";

                // 提示出错
                MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMATION | MB_OK);

                // 返回FALSE
                return FALSE;
            }

            Init(); //对图像的尺寸和调色板信息进行初始化

            // 设置文件名称
            SetPathName(lpszPathName);

            // 复制当前m_Image到m_OImage
            m_OImage = m_Image;

            // 初始化脏标记为FALSE
            SetModifiedFlag(FALSE);

            // 返回TRUE
            return TRUE;
      }

2.5.2 清空图像

接下来,通过菜单命令“文件→清空图像”对图像执行清空操作,清空后效果如图2.5所示。

图2.5 清空后的图像

在“清空图像”菜单响应函数OnFileClean()中,首先要取得2.5.1小节中读入的图像对象,并将它保存在CImgProcess类的临时对象imgInput中;接着需通过检查imgInput.m_pBMIH->biBit-Count的值以确保图像是程序可以处理的8-bpp图像;而后以参数255调用CImg类的InitPixels()函数来完成实际的图像清空操作;最后再将处理后的图像返回给文档类,从而更新了实际的图像对象。

OnFileClean()函数的实现代码如下。

      void CDIPDemoView::OnFileClean()
      {
            // 获取文档对象
            CDIPDemoDoc* pDoc = GetDocument();

            // 输入对象
            CImgProcess imgInput = pDoc->m_Image;

            // 检查图像是灰度图
            if (imgInput.m_pBMIH->biBitCount! =8)
            {
                AfxMessageBox("不是8-bpp灰度图像,无法处理!");
                return;
            }

            imgInput.InitPixels(255); // 清空图像(置白)

            // 将结果返回给文档类
            pDoc->m_Image = imgInput;

            // 设置脏标志
            pDoc->SetModifiedFlag(true);

            // 设置客户区域无效,激发重绘事件
            pDoc->UpdateAllViews(NULL);
      }

2.5.3 像素初始化方法

初始化方法InitPixels()是清空操作的核心,相当于一个简单的图像处理算法。程序中以逐行扫描的方式,依次对每个像素的灰度进行设置,这对应于代码中的二重for循环部分。今后将要学习的很多图像处理算法都是基于这种逐行扫描的基本结构。

InitPixels()函数的实现代码如下。

      /**************************************************
      void CImg::InitPixels(BYTE color)
      功能:      用给定的颜色值初始化图像的所有像素
      限制:      只能使用灰度值提供颜色值,即只能初始化为某种灰色
      参数:      BYTE color:指定的用来初始化图像的灰度值
      返回值:    无
      ***************************************************/
      void CImg::InitPixels(BYTE color)
      {
            //获得图像高、宽
            int nHeight = GetHeight();
            int nWidth = GetWidthPixel();

            int i, j; //行、列循环变量

            if(m_lpData ! = NULL)
            {
                  //逐行扫描图像,依次对每个像素设置color灰度
                  for(int i=0; i<GetHeight(); i++)
                  {
                      for(int j=0; j<GetWidthPixel(); j++)
                      {
                          SetPixel(j, i, RGB(color, color, color));
                      }//for j
                  }//for i
            }
      }

2.5.4 保存图像

最后通过菜单命令“文件→保存”将处理后的图像保存到磁盘。

保存文件的菜单的响应函数OnSaveDocument()的实现代码如下。

      BOOL CDIPDemoDoc::OnSaveDocument(LPCTSTR lpszPathName)
      {
            if(! m_Image.SaveToFile(lpszPathName))
            {
                CString strMsg;
                strMsg = "无法保存BMP图像!";
                // 提示出错
                MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMATION | MB_OK);
                return FALSE;
            }

            // 恢复光标形状
            EndWaitCursor();

            // 重置脏标志为FALSE
            SetModifiedFlag(FALSE);

                return TRUE;
      }