天天看點

【數字圖像處理】四.MFC對話框繪制灰階直方圖

        本文主要講述基于VC++6.0 MFC圖像處理的應用知識,主要結合自己大三所學課程《數字圖像處理》及課件進行回憶講解,主要通過MFC單文檔視圖實作點選彈出對話框繪制BMP圖檔的灰階直方圖,再擷取平均灰階、中指灰階和标準差等值。文章比較詳細基礎,希望該篇文章對你有所幫助~

        免費資源下載下傳位址:

        該篇文章主要是在上一篇文章基礎上進行的講解,其中當打開一張BMP圖像後,點選”直方圖“-》”顯示原圖直方圖“如下。

【數字圖像處理】四.MFC對話框繪制灰階直方圖
【數字圖像處理】四.MFC對話框繪制灰階直方圖

        什麼是灰階直方圖?

        灰階直方圖(histogram)是灰階級的函數,描述的是圖像中每種灰階級像素的個數,反映圖像中每種灰階出現的頻率。橫坐标是灰階級,縱坐标是灰階級出現的頻率。

【數字圖像處理】四.MFC對話框繪制灰階直方圖

        對于連續圖像,平滑地從中心的高灰階級變化到邊緣的低灰階級。直方圖定義為:

【數字圖像處理】四.MFC對話框繪制灰階直方圖

        其中A(D)為門檻值面積函數:為一幅連續圖像中被具有灰階級D的所有輪廓線所包圍的面積。對于離散函數,固定ΔD為1,則:H(D)=A(D)-A(D+1)

        色彩直方圖是高維直方圖的特例,它統計色彩的出現頻率,即色彩機率分布資訊。

        通常這需要一定的量化過程,将色彩分成若幹互不重疊的種類。一般不直接在RGB色彩空間中統計,而是在将亮度分離出來後,對代表色彩部分的資訊進行統計,如在HSI空間的HS子空間、YUV空間的UV子空間,以及其它反映人類視覺特點的彩色空間表示中進行。

        其中直方圖的計算方法如下:

        依據定義,若圖像具有L(通常L=256,即8位灰階級)級灰階,則大小為MxN的灰階圖像f(x,y)的灰階直方圖hist[0…L-1]可用如下計算獲得。

        1、初始化 hist[k]=0; k=0,…,L-1 

        2、統計 hist[f(x,y)]++; x=0,…,M-1, y =0,…,N-1 

        3、歸一化 hist[f(x,y)]/=M*N 

        那麼說了這麼多,直方圖究竟有什麼作用呢?

        在使用輪廓線确定物體邊界時,通過直方圖更好的選擇邊界門檻值,進行門檻值化處理;對物體與背景有較強對比的景物的分割特别有用;簡單物體的面積和綜合光密度IOD可以通過圖像的直方圖求得。

       第一步:建立Dialog

        将視圖切換到ResourceView界面,選中Dialog右鍵滑鼠建立一個Dialog,并建立一個名為IDD_DIALOG_ZFT,設定成下圖對話框。

【數字圖像處理】四.MFC對話框繪制灰階直方圖

        右鍵添加屬性如下:

        對話框-原始直方圖-IDD_DIALOG_ZFT

        組框-RGB-IDC_STATIC_RGB

        圖像-架構-IDC_STATIC_KJ-蝕刻(重點:有它才能添加直方圖在此處,注意GetDlgItem()函數中是IDC而不是IDD對話框)

        添加蝕刻線(圖像蝕刻形成的直線)形如圖中的3個矩形框,并添加靜态文本:Red、Green、Blue、紅、綠、藍、像素、平均灰階、中值灰階、标準差;這些靜态文本都是IDC_STATIC且為預設屬性

        添加紅色4個值(Static)、綠色4個值、藍色4個值,分别為:

        IDC_STATIC_XS_RED(GREEN BLUE)對應像素XS

        IDC_STATIC_PJHD_RED(GREEN BLUE)對應平均灰階PJHD

        IDC_STATIC_ZZHD_RED(GREED BLUE)對應中值灰階ZZHD

        IDC_STATIC_BZC_RED(GREEN BLUE)對應标準差BZC

       第二步:建立類向導MFC ClassWizard

        (1) 在對話框資源模闆空白區輕按兩下滑鼠(Ctrl+W),建立一個新類,命名為CImageZFTDlg會自動生成它的.h和.cpp檔案。在類向導中選中類名CImageZFTDlg,IDs為CImageZFTDlg,WM_INITDIALOG建立這個函數用于初始化。

        (2) 打開類向導,選擇Member Variables頁面,添加如下變量,類型均為CString。

        像素 m_redXS、m_greenXS、m_blueXS

        标準差 m_redBZC、m_greeenBZC、m_blueBZC

        平均灰階 m_redPJHD、m_greenPJHD、m_bluePJHD

        中值灰階 m_redZZHD、m_greenZZHD、m_blueZZHD

【數字圖像處理】四.MFC對話框繪制灰階直方圖

        (3) 在View.cpp中添加直方圖的頭檔案 #inlcude "ImageZFTDlg.h"

        第三步:設定菜單欄調用直方圖對話框

        (1) 将視圖切換到ResourceView界面,選中Menu,在IDR_MAINFRAM中添加菜單項“直方圖”,菜單屬性中選擇“彈出”,在“直方圖”中添加子菜單“顯示原圖直方圖”。

        (2) 設定其屬性為ID_ZFT_YT(顯示直方圖原圖),同時建立類向導,選擇ID_ZFT_YT(IDs),通過COMMAND建立顯示直方圖函數OnZftYt()。

【數字圖像處理】四.MFC對話框繪制灰階直方圖

       第四步:添加代碼及計算4個值

        在ImageProcessingView.cpp中添加如下代碼,注釋中有如何求平均灰階、中值灰階和标準差的消息算法過程。

        第五步:此時運作結果如下圖所示,打開圖檔可以顯示參數。

【數字圖像處理】四.MFC對話框繪制灰階直方圖

        重點(極其重要*)

        (1) 如何在MFC中(View中)實作對子對話框的畫圖或直方圖響應?

        解決方法:在子對話框中.cpp檔案中實作畫圖響應,不要再View.cpp中實作,否則圖像會以menu背景為坐标,而在ImageZFTDlg.cpp中建立OnPaint函數實作畫圖,它預設會以子對話框為标準。

        (2) 如何把View.cpp中的圖檔像素直方圖資訊傳遞給子對話框ImageZFTDlg.cpp呢?

        解決方法:如果自定義ImageStruct.h中建立全局變量,每個.cpp中引用該頭檔案調用總是報錯(未知),是以我在View.h中建立一個全局變量int Red[256];再在子檔案.cpp中函數裡調用該全局變量即可extern int Red[256],這是非常重要的一個C語言知識。

        (3) 畫圖函數OnPaint()參考源代碼中詳細注釋。

        如何繪制坐标軸、文字、圖像,其實自己繪制而沒調用第三方庫還是挺有意思的。

        第一步:建立畫直方圖函數OnPaint

        打開類向導(Ctrl+W),類名選擇CImageZFTDlg,IDs選擇CImageZFTDlg,在Message函數中建立WM_PAINT映射,預設函數名為OnPaint建立函數void CImageZFTDlg::OnPaint()

        第二步:繪制直方圖大緻思想如下

        (1) 重點:擷取要繪制直方圖的位置和圖像資源的對應号ID(IDC_STATIC_KJ 架構),我當時認為繪制直方圖隻能繪制到”圖像“控件IDC中,不能是對話框IDD。

        CWnd *pWnd = GetDlgItem(IDC_STATIC_KJ);

        CDC *pDC = pWnd->GetDC();

        (2) 擷取對話框矩形的長和寬

        CRect rectpic;

        GetDlgItem(IDC_STATIC_KJ)->GetWindowRect(&rectpic);

        (3) 建立畫筆對象并對畫筆進行顔色設定

        CPen *RedPen = new CPen();

        RedPen->CreatePen(PS_SOLID,1RGB(255,0,0));

        (4) 選中目前畫筆并儲存以前畫筆

        CGdiObject *RedOlderPen = pDC->SelectObject(RedPen);

        (5) 繪制直方圖(圖像坐标自己算)

        矩形 pDC->Rectangle(9,327,312,468);

        移動 pDC->MoveTo(15,331);

        直線 pDC->LineTo(15,488);

        文字 pDC->TextOut(15+48*i,450,str);

        (6) 恢複以前畫筆

        pDC->SelectObject(RedOlderPen);

        delete RedPen;

        ReleaseDC(pDC);

        第三步:源代碼與詳細注釋思想

        在ImageZFTDlg.cpp中修改OnPaint函數:

        此時運作程式即可顯示直方圖。

        最後還是希望文章對你有所幫助,如果文章有不足或錯誤之處,請海涵~文章不僅僅講述了直方圖相關的知識,同時文章也給你提供了一種繪制坐标圖像的思想和詳細注釋。有時候一直懷疑回憶這些知識會讓我停滞不前,但心安即好,何必在意!

        從來沒有什麼終南捷徑和大神,真正的捷徑隻有三個:堅持、專注、認真。其他的都是細枝末節,做到這三個,其他的自然而然都會擁有。——同學CY

繼續閱讀