您的位置:首页 > 编程语言 > C语言/C++

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

2014-02-10 11:23 591 查看
本节主要内容是将图片显示到控件上。

这里我们借助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

中给出



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