VC++开发数字图像处理系统2
来源:互联网 发布:java包装类有啥用 编辑:程序博客网 时间:2024/06/14 08:24
本节主要内容是将图片显示到控件上。
这里我们借助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 CDialog12 {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 else106 {;}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 else117 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 else168 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 else188 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 else208 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 else228 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
中给出
- VC++开发数字图像处理系统2
- VC++2010开发数字图像系统1
- VC数字图像处理编程讲座 2
- VC数字图像处理编程
- VC数字图像处理
- VC数字图像处理编程
- VC数字图像处理编程
- VC数字图像处理编程之一
- VC数字图像处理编程讲座
- VC数字图像处理编程讲座
- VC数字图像处理编程讲座
- VC数字图像处理编程(转载)
- VC数字图像处理编程之一
- VC数字图像处理编程讲座之八(2)
- VC数字图像处理编程讲座之八(2)
- VC数字图像处理编程讲座之四
- VC数字图像处理编程讲座之五
- VC数字图像处理编程讲座[转载]
- 内存分配中堆与栈的区别
- 回顾下最小重量机器设计问题
- 计算机视觉领域的一些牛人博客,超有实力的研究机构等的网站链接
- 我的计算机资料下载地址
- 动态链接库DLL的创建和使用
- VC++开发数字图像处理系统2
- 语音信号MFCC的特征提取Matlab源码
- 语音特征MFCC的求解过程
- 【Chrome】如何在C++中增加给JavaScript调用的API
- mysql 的一些 tips
- 关于Android x86平台 函数hook知识的一点记录
- OpenGL 法线贴图 切线空间 整理
- 学习VC++时经常会遇到链接错误LNK2001
- google breakpad使用心得