• 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

    中给出

  • 相关阅读:
    洛谷 P1494 [国家集训队]小Z的袜子 /【模板】莫队
    洛谷 P2801 教主的魔法
    数据库三范式
    vi和vim三种常见模式
    linux目录结构的具体介绍
    Linux怎么用root用户登录
    虚拟机的网络连接的三种方式
    事务
    数据库存储引擎
    delete和truncate
  • 原文地址:https://www.cnblogs.com/sxzheng/p/3112675.html
Copyright © 2020-2023  润新知