VC++开发数字图像处理系统2

本节主要内容是将图片显示到控件上。

这里我们借助VS提供给我们的Gdiplus工具将图片显示到控件上。

一、首先简要介绍Gdiplus的配置方法:

1    在单文档应用程序中使用GDI+

创建一个单文档程序

1.1   添加包含文件和类库,方法:在stdafx.h文件中添加下面两行代码

#include

#pragma comment(lib,”gdiplus.lib”)

using namespace Gdiplus;

或者【项目】|【属性】,->【链接器】|【输入】->【附加依赖项】,在框中输入gdiplus.lib

1.2  在应用程序项目的应用类中,添加一个成员变量

ULONG_PTR m_gdiplusToken;
其中,ULONG_PTR是一个DWORD数据类型,该成员变量用来保存GDI+被初始化后在应用程序中的GDI+标识,以便能在应用程序退出后,引用该标识来调用Gdiplus:: GdiplusShutdown来关闭GDI+

1.3   在应用类中添加ExitInstance的重载来关闭GDI+

int CEXXXApp::ExitInstance()

{

                Gdiplus::GdiplusShutdown(m_gdiplusToken);

                return CWinApp::ExitInstance();

}

1.4  在应用类的InitInstance函数中添加GDI+的初始化代码

BOOL CEx_GDIPlusApp::InitInstance()

{

    ......

    CWinApp::InitInstance();

    Gdiplus::GdiplusStartupInput gdiplusStartupInput;

Gdiplus::GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL);

              ......

        }             

2    在基于对话框应用程序中使用GDI+

创建一个对话框应用程序

2.1 添加包含文件和类库,方法:在stdafx.h文件中添加下面两行代码

#include

#pragma comment(lib,”gdiplus.lib”)

using namespace Gdiplus;

2.2以下步骤同单文档应用程序

3    VS2010中的MFC中配置GDI+
首先,VS2010中已经有GDI+SDK包的,不需要额外下载
1)stdafx.h文件中加入下面3行代码,添加相应的头文件和库
  #pragma comment( lib, "gdiplus.lib" )
  #include "gdiplus.h"
  using namespace Gdiplus;
2)在应用程序项目的应用类中,添加一个成员变量或者定义一个全局变量ULONG_PTR m_gdiplusToken;
其中,ULONG_PTR是一个DWORD数据类型,该成员变量用来保存GDI+被初始化后在应用程序中的GDI+标识,以便能在应用程序退出后,引用该标识来调用Gdiplus:: GdiplusShutdown来关闭GDI+
3)使用GDI+函数前,先,最好放在OnInitDialog()中
 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
 Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); 
4)使用完GDI+函数后,需要卸载GDI+
  Gdiplus::GdiplusShutdown(m_gdiplusToken);

这就是基本的配置了

当然,为了避免命名冲突,也可以将

#include

#pragma comment(lib,”gdiplus.lib”)

using namespace Gdiplus;

只添加到我们要使用Gdiplus库的头文件中去。

二、将图片显示到控件上

这里我们插入一个对话框资源:IDC_ThresholdDlg

再为这个资源添加一个类:CThreshholdDlg

CThreshholdDlg.h

 1 #pragma once
 2 
 3 #include "resource.h"
 4 #include "Dib.h"
 5 #include "Threshold.h"
 6 #pragma comment(lib,"gdiplus.lib")
 7 #include <GdiPlus.h>
 8 using namespace Gdiplus;
 9 // CThresholdDlg 对话框
10 
11 class CThresholdDlg : public CDialog
12 {
13     DECLARE_DYNAMIC(CThresholdDlg)
14 
15 public:
16     CThresholdDlg(CWnd* pParent = NULL);   // 标准构造函数
17     virtual ~CThresholdDlg();
18 
19 // 对话框数据
20     enum { IDD = IDD_Threshold };
21 
22 public:
23     CDib dib;
24     CStatic m_staBmp;
25     CString m_BmpFilePath;
26     CString m_BmpFileName;
27 public:
28     CDib* GetDib();
29     void DrawBitmap();
30 protected:
31     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
32 
33     DECLARE_MESSAGE_MAP()
34 public:
35     afx_msg void OnBnClickedOpenBmp();
36     afx_msg void OnBnClickedOutsthreshold();
37     afx_msg void OnBnClickedAdaptivethreshold();
38     afx_msg void OnBnClickedSaveresult();
39 };

CThresholdDlg.cpp

  1 // ThresholdDlg.cpp : 实现文件
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "ImgPro.h"
  6 #include "ThresholdDlg.h"
  7 #include "afxdialogex.h"
  8 
  9 
 10 // CThresholdDlg 对话框
 11 
 12 IMPLEMENT_DYNAMIC(CThresholdDlg, CDialog)
 13 
 14 CThresholdDlg::CThresholdDlg(CWnd* pParent /*=NULL*/)
 15     : CDialog(CThresholdDlg::IDD, pParent)
 16 {
 17 
 18 }
 19 
 20 CThresholdDlg::~CThresholdDlg()
 21 {
 22 }
 23 
 24 void CThresholdDlg::DoDataExchange(CDataExchange* pDX)
 25 {
 26     CDialog::DoDataExchange(pDX);
 27     DDX_Control(pDX,IDC_STATIC,m_staBmp);
 28 }
 29 
 30 
 31 BEGIN_MESSAGE_MAP(CThresholdDlg, CDialog)
 32     ON_BN_CLICKED(IDC_Open_BMP, &CThresholdDlg::OnBnClickedOpenBmp)
 33     ON_BN_CLICKED(IDC_OutsThreshold, &CThresholdDlg::OnBnClickedOutsthreshold)
 34     ON_BN_CLICKED(IDC_AdaptiveThreshold, &CThresholdDlg::OnBnClickedAdaptivethreshold)
 35     ON_BN_CLICKED(IDC_SaveResult, &CThresholdDlg::OnBnClickedSaveresult)
 36 END_MESSAGE_MAP()
 37 
 38 CDib* CThresholdDlg::GetDib()
 39 {
 40     return &dib;
 41 }
 42 
 43 void CThresholdDlg::DrawBitmap(void)
 44     {
 45         CDC* pDC=m_staBmp.GetDC();
 46         Graphics graph(pDC->GetSafeHdc());
 47         CRect rect;
 48         m_staBmp.GetClientRect(rect);
 49         pDC->FillRect(rect, &CBrush(RGB(211, 211, 211)));
 50         CSize size;
 51         size.cx=rect.Width();
 52         size.cy=rect.Height();
 53         dib.Draw(pDC,CPoint(0,0),size);
 54         ReleaseDC(pDC);
 55     }
 56 // CThresholdDlg 消息处理程序
 57 
 58 
 59 void CThresholdDlg::OnBnClickedOpenBmp()
 60 {
 61     // TODO: 在此添加控件通知处理程序代码
 62     LPCTSTR lpszFilter=L"BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg)|*.jpg|All Files(*.*)|*.*||";
 63     CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER,lpszFilter,NULL);
 64     CFile file;
 65     if(dlg.DoModal()==IDOK)
 66     {
 67         m_BmpFilePath=dlg.GetPathName();
 68         if(file.Open(m_BmpFilePath,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
 69         {
 70             return;
 71         }
 72         dib.LoadFromFile(m_BmpFilePath);
 73         DrawBitmap();
 74     }
 75 }
 76 
 77 
 78 void CThresholdDlg::OnBnClickedOutsthreshold()
 79 {
 80     // TODO: 在此添加控件通知处理程序代码
 81     CThreshold threshold(GetDib());
 82     //threshold.m_pDib=GetDib();
 83     if(!dib.IsGrade())
 84         {
 85             dib.RgbToGrade();
 86             DrawBitmap();
 87         }
 88         else
 89         {;}
 90     threshold.OtusThreshold();
 91     DrawBitmap();
 92 }
 93 
 94 
 95 void CThresholdDlg::OnBnClickedAdaptivethreshold()
 96 {
 97     // TODO: 在此添加控件通知处理程序代码
 98     CThreshold threshold(GetDib());
 99     //threshold.m_pDib=GetDib();
100     if(!dib.IsGrade())
101         {
102             dib.RgbToGrade();
103             DrawBitmap();
104         }
105         else
106         {;}
107     threshold.AdaptiveThreshold();
108     DrawBitmap();
109 }
110 
111 
112 void CThresholdDlg::OnBnClickedSaveresult()
113 {
114     // TODO: 在此添加控件通知处理程序代码
115     LPCTSTR lpszFilter=L"BMP Files(*.bmp)|*.bmp|All Files(*.*)|*.*||";
116         CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_EXPLORER,lpszFilter,NULL);
117         if(dlg.DoModal()!=IDOK)
118             return;
119         dib.SaveToFile(dlg.GetPathName());
120 }

Threshold.h

 1 #pragma once
 2 
 3 #include "Dib.h"
 4 
 5 class CThreshold
 6 {
 7 public:
 8     CThreshold();
 9     CThreshold(CDib *pDib);
10 public:
11     ~CThreshold(void);
12 public:
13     void AdaptiveThreshold(void);
14     void OtusThreshold(void);
15 private:
16     CDib * m_pDib; 
17 };

Threshold.cpp

  1 #include "StdAfx.h"
  2 #include "Threshold.h"
  3 #include "math.h"
  4 
  5 CThreshold::CThreshold()
  6 {
  7 }
  8 
  9 CThreshold::CThreshold(CDib *pDib)
 10 {
 11     m_pDib = pDib;
 12 }
 13 
 14 CThreshold::~CThreshold(void)
 15 {
 16 }
 17 
 18 //=======================================================
 19 // 函数功能: 最大方差阈值分割
 20 // 输入参数: 无
 21 // 返回值:   无
 22 //=======================================================
 23 void CThreshold::OtusThreshold(void)
 24 {
 25     // 循环变量
 26     int i, j;
 27 
 28     // 原图数据区指针
 29     LPBYTE p_data;
 30     p_data = m_pDib->GetData();
 31 
 32     // 图像每行像素所占的字节数
 33     int nLineByte = m_pDib->GetLineByte();
 34 
 35     // 图像的宽度
 36     int nWidth = m_pDib->GetWidth();
 37 
 38     // 图像的高度
 39     int nHeight = m_pDib->GetHeight();
 40 
 41     // 灰度直方图数组,并初始化
 42     int nGrayHistogram[256];
 43     memset(nGrayHistogram, 0, sizeof(nGrayHistogram));
 44      
 45     // 统计各个灰度级对应的像素个数,并存放到灰度直方图数组中
 46     int nPixel;
 47     for (j = 0; j < nHeight; j ++)
 48         for (i = 0; i < nWidth; i ++)
 49         {
 50             // 获取当前像素点的灰度值
 51             nPixel = p_data[nLineByte * j + i];    
 52 
 53             // 对灰度值统计计数
 54             nGrayHistogram[nPixel] ++;        
 55         }
 56 
 57     // c0组和c1组的均值
 58     float u0, u1;
 59 
 60     // c0组和c1组的概率
 61     float w0, w1;
 62 
 63     // c0组的像素总数
 64     int nCount0;
 65 
 66     // 阈值和最佳阈值(对应方差最大时的阈值)
 67     int nT, nBestT;
 68 
 69     // 方差和最大方差
 70     float fVaria, fMaxVaria = 0;
 71 
 72     // 统计直方图中像素点的总数,并存放到nSum中
 73     int nSum=0;
 74     for(i = 0; i < 256; i ++)
 75         nSum += nGrayHistogram[i];
 76 
 77 
 78     // 令阈值nT从0遍历到255
 79     for(nT = 0; nT < 256; nT ++)
 80     {
 81         // 当阈值为nT时,计算c0组的均值和概率
 82         u0 = 0;
 83         nCount0 = 0;
 84         for(i = 0; i <= nT; i++)
 85         {
 86             u0 += i * nGrayHistogram[i];
 87             nCount0 += nGrayHistogram[i];
 88         }
 89         u0 /= nCount0;
 90         w0 = (float) nCount0 / nSum;
 91 
 92         // 当阈值为nT时,计算c1组的均值和概率
 93         u1 = 0;
 94         for(i = nT+1; i < 256; i ++)
 95              u1 += i * nGrayHistogram[i];
 96         u1 /= (nSum - nCount0);
 97         w1 = 1 - w0;
 98 
 99         // 计算两组间的方差
100         fVaria = w0 * w1 * (u0 - u1) * (u0 - u1);
101 
102         // 记录最大方差和最佳阈值
103         if(fVaria > fMaxVaria)
104         {
105             fMaxVaria = fVaria;
106             nBestT = nT;
107         }
108     }
109 
110     // 利用最佳阈值对原图像作分割处理
111     for(j = 0; j < nHeight; j ++)
112         for(i = 0; i < nWidth; i ++)
113         {
114             if(p_data[j * nLineByte + i] < nBestT)
115                 p_data[j * nLineByte + i] = 0;
116             else
117                 p_data[j * nLineByte + i] = 255;
118         }
119 }
120 
121 
122 //=======================================================
123 // 函数功能: 自适应阈值分割
124 // 输入参数: 无
125 // 返回值:   无
126 //=======================================================
127 void CThreshold::AdaptiveThreshold(void)
128 {
129     // 循环变量
130     int i,j;
131     
132     // 原图像数据区指针
133     LPBYTE p_data;
134     p_data = m_pDib->GetData();
135 
136     // 图像每行像素所占的字节数
137     int nLineByte = m_pDib->GetLineByte();
138 
139     // 图像的宽度
140     int nWidth = m_pDib->GetWidth();
141 
142     // 图像的高度
143     int nHeight = m_pDib->GetHeight();
144 
145     // 局部阈值
146     int nThreshold[2][2];
147 
148     // 子图像的灰度平均值
149     int nAvgValue;
150 
151     // 对左上图像逐点扫描,计算该子图像的灰度平均值
152     nAvgValue = 0;
153     for(j = nHeight / 2; j < nHeight; j ++)
154         for(i = 0; i < nWidth / 2; i ++)
155             nAvgValue += p_data[j * nLineByte + i];
156     nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
157 
158     // 设置阈值为子图像的平均值
159     nThreshold[0][0] = nAvgValue;
160 
161     // 对左上图像逐点扫描并进行阈值分割
162     for(j = nHeight / 2; j < nHeight; j ++)
163         for(i = 0; i < nWidth / 2; i ++)
164         {
165             if(p_data[j * nLineByte + i] < nThreshold[0][0])
166                 p_data[j * nLineByte + i] = 0;
167             else
168                 p_data[j * nLineByte + i] = 255;
169         }
170 
171     // 对右上图像逐点扫描,计算该子图像的灰度平均值
172     nAvgValue = 0;
173     for(j = nHeight / 2; j < nHeight; j ++)
174         for(i = nWidth / 2; i < nWidth; i ++)
175             nAvgValue += p_data[j * nLineByte + i];
176     nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
177 
178     // 设置阈值为子图像的平均值
179     nThreshold[0][1] = nAvgValue;
180 
181     // 对右上图像逐点扫描并进行阈值分割
182     for(j = nHeight / 2; j < nHeight; j ++)
183         for(i = nWidth / 2; i < nWidth; i ++)
184         {
185             if(p_data[j * nLineByte + i] < nThreshold[0][0])
186                 p_data[j * nLineByte + i] = 0;
187             else
188                 p_data[j * nLineByte + i] = 255;
189         }
190 
191     // 对左下图像逐点扫描,计算该子图像的灰度平均值
192     nAvgValue = 0;
193     for(j = 0; j < nHeight / 2; j ++)
194         for(i = 0; i < nWidth / 2; i ++)
195             nAvgValue += p_data[j * nLineByte + i];
196     nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
197 
198     // 设置阈值为子图像的平均值
199     nThreshold[1][0] = nAvgValue;
200 
201     // 对左下图像逐点扫描并进行阈值分割
202     for(j = 0; j < nHeight / 2; j ++)
203         for(i = 0; i < nWidth / 2; i ++)
204         {
205             if(p_data[j * nLineByte + i] < nThreshold[0][0])
206                 p_data[j * nLineByte + i] = 0;
207             else
208                 p_data[j * nLineByte + i] = 255;
209         }
210 
211     // 对右下图像逐点扫描,计算该子图像的灰度平均值
212     nAvgValue = 0;
213     for(j = 0; j < nHeight / 2; j ++)
214         for(i = nWidth / 2; i < nWidth; i ++)
215             nAvgValue += p_data[j * nLineByte + i];
216     nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
217 
218     // 设置阈值为子图像的平均值
219     nThreshold[1][1] = nAvgValue;
220 
221     // 对右下下图像逐点扫描并进行阈值分割
222     for(j = 0; j < nHeight / 2; j ++)
223         for(i = nWidth / 2; i < nWidth;i ++)
224         {
225             if(p_data[j * nLineByte + i] < nThreshold[0][0])
226                 p_data[j * nLineByte + i] = 0;
227             else
228                 p_data[j * nLineByte + i] = 255;
229         }
230 }

最后我们在视图类的实现(C*View.cpp)文件里添加命令响应函数:

1 void CImgProView::OnThreshhold()
2 {
3     // TODO: 在此添加命令处理程序代码
4     CThresholdDlg thresholddlg;
5     thresholddlg.DoModal();
6 }

注:Dib.h和Dib.cpp文件在

VC++2010开发数字图像系统1

中给出

本书用面向对象的方法向读者介绍了用Visual C++进行数字图像处理的方法和技巧。全书共分13章,内容涵盖了数字图像概述、Visual C++数字图像编程基础、图像的几何变换、图像的灰度变换、图像的正交变换、图像增强、图像复原、图像的压缩编码、边缘检测与图像分析、图像的数学形态学运算、图像融合,以及图像特技显示等,在本书最后综合运用了图像处理的多种理论和方法实现了一个人脸检测的案例,以助于读者对各种图像处理方法的系统掌握和综合应用。. 在进行原理介绍时,力求通俗易懂,简明扼要而又不失完整性。在代码实现时力求简洁明了,注释详尽,为读者的阅读和理解提供最大便利。.. 本书的特色决定了本书不但适用于初、中级读者,其中的部分内容对高级读者也有一定的参考价值,同时也可用作高校相关专业师生的参考教材。... 【目录信息】 第1章 数字图像概述. 1.1 数字图像概论 1.2 数字图像的存储 1.3 BMP图像文件格式 1.4 TIFF图像文件格式 1.5 JPEG图像文件格式 1.6 PNG图像文件格式 1.7 小结 第2章 数字图像编程基础 2.1 图像和调色板的基本概念 2.2 GDI位图(DDB) 2.3 设备无关位图(DIB) 2.4 构造CDib类 2.5 使用CDib类读写BMP文件示例 2.6 小结 第3章 图像增强 3.1 灰度变换修整法 3.2 直方图修整法 << 查看详细目录 【前言】 20世纪20年代,图像处理首次应用于改善伦敦和纽约之间通过海底电缆传送的图片质量。经过几十年的研究与发展,数字图像处理的理论和方法进一步完善,应用领域更加广阔,已经成为一门新兴的学科,并在向更高级的方向发展。如在景物理解和计算机视觉(机器视觉)方面,图像处理已由二维处理发展到三维理解或解释。近几年来,随着计算机和各个相关领域研究的迅速发展,科学计算可视化、多媒体技术等研究和应用的兴起,数字图像处理从一个专门领域的学科,变成了一种新型的科学研究和人机界面的工具。. Visual C++是Microsoft公司推出的一种高度综合性能的开发Win32环境程序,面向对象的可视化集成编程系统。用..
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值