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

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

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

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

1    在单文档应用程序中使用GDI+创建一个单文档程序

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

#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文件中添加下面两行代码

#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);

这就是基本的配置了

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

#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 };

 

  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

 /** 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

  /**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)文件里添加命令响应函数:

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

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

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

中给出

posted @ 2013-06-01 17:22  imeeee  阅读(779)  评论(0编辑  收藏  举报