天天看點

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        本文主要講述基于VC++6.0 MFC圖像處理的應用知識,主要結合自己大三所學課程《數字圖像處理》及課件進行講解,主要通過MFC單文檔視圖實作顯示BMP格式圖檔,并通過Bitmap進行灰階處理、圖檔采樣和量化功能。

        個人認為對初學者VC++6.0可能還是很值得學習的工具,是以采用它來講解,而不是VS或C#。同時文章比較詳細基礎,希望該篇文章對你有所幫助~

        免費資源下載下傳位址:

        第一步:建立項目"MFC AppWizard(exe)",項目名為ImageProcessing,在應用程式類型中選擇"單個文檔",點選"确定"。在左欄的"資源視圖"中,點選"Menu->IDR_MAINFRAM"可以檢視并修改菜單視圖。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第二步:向CImageProcessingView類添加成員變量和成員函數。在右欄的"類視圖"右鍵ImageProcessingView添加函數或直接在ImageProcessingView.h中直接添加public成員變量和成員函數。添加代碼如下:

      同時采用類視圖添加後,會自動在XXXView.h中添加函數定義,在XXXView.cpp中添加函數實作代碼。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解
【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第三步:編輯ImageProcessingView.cpp中ShowBitmap()函數。通過它顯示BMP圖檔,其中代碼及詳細注釋如下:

        第四步:設定打開BMP圖檔函數。"檢視"->"建立類向導"(Ctrl+W)->選擇"類名"CImageProcessing->在指令對象ID中輕按兩下"ID_FILE_OPEN"->自動生成預設成員函數OnFileOpen,消息為COMMAND。輕按兩下成員函數(Member

Functions)進入函數編輯。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        編輯ImageProcessingView.cpp函數實作打開圖檔,代碼如下:

        第五步:在ImageProcessingView.cpp中找到OnDraw()函數,通過OnDraw()函數調用ShowBitmap()函數顯示圖檔。代碼如下:

        第六步:此時點選運作,同時點選檔案-打開,即可顯示圖檔如下圖所示:

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        PS:這是非常著名的一張圖檔萊娜圖(Lenna),全圖是一張花花公子封面的裸圖,後成為數字圖像處理的标志圖檔。哈哈~至于BMP圖檔格式參照第一篇文章

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        在很多進行中,都需要擷取BMP圖像的一些資料,如圖像寬度、高度、像素大小等,後面的處理與之相關,主要的是ReadBmp函數。

       第一步:在XXXView.h中添加BMP格式圖像相關的成員變量和成員函數,其中成員函數通過類視圖右鍵添加,成員變量可以在XXXView.h中直接複制。

        第二步:在ImageProcessingView.cpp中實作ReadBmp函數和SaveBmp函數。

       其中SaveBmp()函數代碼如下:

        第三步:添加儲存menu控件和函數。點選”檢視-建立類向導“,在ID清單中找到ID_FILE_SAVE,點選COMMAND(Message清單),輕按兩下添加預設成員函數OnFileSave,同時在Member

Functions(成員函數)中輕按兩下該函數進入函數并編輯。添加如下代碼:

        第四步:在XXXView.cpp中OnDraw()函數中調用讀取圖檔函數。

       if( EntName.Compare(_T("bmp"))

== 0 )      //bmp格式  

        {  

                ReadBmp();

                ShowBitmap(pDC,BmpName);               //顯示圖檔  

        }  

        運作程式,打開圖檔點選儲存即可實作。重點是ReadBmp擷取一些重要參數。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        什麼叫灰階圖?任何顔色都有紅、綠、藍三原色組成,假如原來某點的顔色為RGB(R,G,B),那麼我們可以通過下面幾種方法,将其轉換為灰階:

        浮點算法:Gray=R*0.3+G*0.59+B*0.11

        整數方法:Gray=(R*30+G*59+B*11)/100

        移位方法:Gray=(R*28+G*151+B*77)>>8;

        平均值法:Gray=(R+G+B)/3;(此程式采用算法)

        僅取綠色:Gray=G;

        通過上述任一種方法求得Gray後,将原來的RGB(R,G,B)中的R,G,B統一用Gray替換,形成新的顔色RGB(Gray,Gray,Gray),用它替換原來的RGB(R,G,B)就是灰階圖了。

        改變象素矩陣的RGB值,來達到彩色圖轉變為灰階圖

        權重平均值算法:根據光的亮度特性,其實正确的灰階公式應當是:

                                                R=G=B=R*0.299+G*0.587+B0.144

        為了提高速度我們做一個完全可以接受的近似,公式變形如下:R=G=B=(R*3+G*6+B)/10 

        第一步:在前面的代碼基礎上繼續,先在ImageProcessingView.h中添加成員變量m_bitmaplin和BmpNameLin,因為後面處理操作是處理備份檔案與原圖進行比較。

        第二步:在ImageProcessingView.cpp中ShowBitmap()函數前添加變量numPicture和level。

        第三步:修改ImageProcessingView.cpp中OnFileOpen()函數,添加臨時變量名和顯示一張圖檔标志變量。代碼如下:

        第四步:将視圖切換到ResourceView界面,選中Menu->在IDR_MAINFRAME中添加菜單”顯示“,輕按兩下它在菜單屬性中選擇”彈出“。在”顯示“的子菜單中添加:

        雙圖顯示--ID_SHOW_TWO(ID)--預設屬性

        灰階圖檔--ID_SHOW_HD(ID)--預設屬性

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第五步:點選"檢視"->"建立類向導"(Ctrl+W),選擇CImageProcessing類,然後ID_SHOW_TWO,輕按兩下COMMAND(Message),生成預設成員函數。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        在XXXView.cpp中實作OnShowTwo()函數,代碼如下:

        第六步:同上面相同的方法,"檢視"->”建立類向導“->ID_SHOW_HD(ID)->COMMAND(Message),預設成員函數名。在XXXView.cpp添加代碼如下:

        第七步:修改ShowBitmap()函數中雙顯部分,添加如下代碼:

        雙顯和灰階運作效果如下圖所示:

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        圖像數字化包括量化和取樣兩個過程,其中:

        量化:幅值f(x,y)的離散化,f(x,y)表示靜止灰階圖像的空間坐标

        取樣:對空間連續坐标(x,y)的離散化

        一幅行數為M、列數為N的圖像大小為M×N的矩陣形式為:(其中矩陣中每個元素代表一個像素)

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        該工程所有的處理都基于24位的bmp格式圖檔的處理,24為表示biBitCount=24,1個像素占3個位元組(red、green、blue)。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        如圖量化級不同産生的灰階也不同,量化是使連續信号的幅度用有限級的數位表示的過程。

        量化等級=2:使用2種灰階級(0~255)表示圖檔,小于128的取0,大于等于128的取128。把位圖資料塊所有資料在臨時圖檔中取值,在顯示即可。

        量化等級=4:使用4種灰階級顯示圖檔,就會發現圖檔分層為4種顔色。同時,0-64區間取0,64-128區間取64,128-192區間取128,192-255區間取192。

        量化的取值各不相同,我采用的是最簡單的取值。其它方法可自己去查閱資料。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解
【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第一步:設定菜單欄。将試圖切換到ResourceView界面--選中Menu--在IDR_MAINFRAME中添加菜單“量化”--輕按兩下它在菜單屬性中選擇“彈出”。在“顯示”的子菜單中添加:屬性為預設屬性。

        量化 Level 2--ID_LH_2       量化 Level 4--ID_LH_4

        量化 Level 8--ID_LH_8       量化 Level 16--ID_LH_16

        量化 Level 32--ID_LH_32   量化 Level 64--ID_LH_64

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第二步:建立類向導。檢視->建立類導向(Ctrl+W)->CXXXView(類名)->ID_LH_2->COMMAND(Messages)->預設成員函數名。相同方法分别為量化等級2、4、8、16、32、64建立類導向。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第三步:在ImageProcessingView.cpp中編輯灰階函數。代碼如下:

        核心流程是打開兩張圖檔原圖(BmpName)和臨時圖檔(BmpNameLin),然後讀取原圖資訊頭指派給臨時處理圖檔,在讀取原圖m_nImage整個像素矩陣,量化處理每個像素(即分等級量化),最後檔案寫量化後的像素矩陣給BmpNameLin,在指派全局變量level\numPicture和調用Invalidate()重繪圖像即可。

        第四步:修改ShowBitmap()函數,顯示量化處理。添加如下代碼:

        運作效果如下圖,當量化Level=2時很明顯的兩種灰階顔色,Level=4有4種顔色。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        該工程所有的處理都基于24位的bmp格式圖檔的處理,24為表示biBitCount=24,1個像素占3個位元組(red、green、blue)。如圖一張512*512的原圖,保持灰階級256不變後的各種采樣。輸入采樣坐标:如16*16,它的含義是原圖512*512像素,現在組成一個新的圖檔為16*16像素,(512/16=32,512/16=32)則每32*32組成一個新的區域。共有這種區域16*16個,采樣的方法有2種:

        a.把這個32*32區域全部指派成左上角那個像素,這樣圖檔的大小不變,困難在于指派要4層循環。(項目中采用的就是這種方法)

        b.把這個32*32區域的左上角取出來,組成一個新的圖檔,共有16*16個像素,這張圖檔的大小要變小,隻有16*16個像素。但難點在于同時要把bmp檔案頭中的圖檔大小、資訊頭中的長寬像素改變、偏移量等資訊更新。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        又如下圖所示:

        原圖8*8的矩陣要處理成3*3的矩陣,則循環先處理第一二行,①②④⑤為3*3處理,去左上角的RGB,③⑥為2*3的處理;重點是原圖讀取一維數組需要轉成二維數組指派處理;最後再處理最後一行資料。采樣中公式為:

        //擷取填充顔色 相當于一次讀取一個像素的RGB值再乘3跳3個位元組

        red=m_pImage[(X+Y*m_nWidth)*3];

        green=m_pImage[(X+Y*m_nWidth)*3+1];

        blue=m_pImage[(X+Y*m_nWidth)*3+2];

        //填出圖像循環 小區域中的長寬循環

        //(X+Y*m_nWidth)*3跳到該小區域 再指派3*3小區域的RGB 同一區域RGB相同

        m_pImage[(X+Y*m_nWidth)*3+m+n*m_nWidth*3]=red; m++;

        m_pImage[(X+Y*m_nWidth)*3+m+n*m_nWidth*3]=green; m++;

        m_pImage[(X+Y*m_nWidth)*3+m+n*m_nWidth*3]=blue; m++;

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        PS:難點是還未處理剩餘部分的采樣。

第一步:設定菜單欄

        a.将視圖切換到ResourceView界面--選中Menu--在IDR_MAINFRAME中添加菜單“采樣”--輕按兩下它在菜單屬性中選擇“彈出”;

        b.在“采樣”的子菜單中添加:屬性為預設屬性。ID_CY--圖檔采樣。

        c.建立類導向:檢視--建立類導向(Ctrl+W)--CImageProcessingView(類名)--ID_CY--COMMAND(Messages)--預設成員函數名。生成void CImageProcessingView::OnCy()采樣函數。

        第二步:設定采樣對話框

        a.将試圖切換到ResourceView界面--選中Dialog,右鍵滑鼠建立一個Dialog,并建立一個名為IDD_DIALOG_CY。編輯框(X)IDC_EDIT_CYX 和 (Y)IDC_EDIT_CYY,确定為預設按鈕。設定成下圖對話框:

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        b.在對話框資源模闆空白區域輕按兩下滑鼠—Create a new class建立一個新類--命名為CImageCYDlg。會自動生成它的.h和.cpp檔案。類向導Ctrl W--類名:CImageCYDlg--CImageCYDlg(IDs)—WM_INITDLAOG建立這個函數可以用于初始化。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        c.打開類向導Ctrl+W--選擇MemberVariables頁面,類名:CImageCYDlg--Add Variables--設定成:

                IDC_EDIT_CYX--int--m_xPlace

                IDC_EDIT_CYY--int--m_yPlace

        d.在View.cpp中添加采樣的頭檔案#include "ImageCYDlg.h"

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        第三步:在ImageProcessingView.cpp中添加代碼

        第四步:修改ShowBitmap(CDC* pDC,CString BmpName)中的代碼:

        else if(level==3) //圖檔采樣

        {

          m_hBitmapChange = (HBITMAP) LoadImage(NULL,BmpNameLin,IMAGE_BITMAP,0,0,

                 LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);

        }

        運作效果如下圖所示,其中彩色圖檔應該先灰階處理再進行其他操作。

【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解
【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解
【數字圖像處理】三.MFC實作圖像灰階、采樣和量化功能詳解

        總結:後悔當初還沒有寫部落格,通過回憶幾年前的代碼,很多當時的體會和思想都已不複存在了!可能你在百度文庫中看到類似的文章,因為那些都是我在2012年上傳的,最初是通過它進行分享程式設計知識的,後來發現了更好的CSDN而取代之。這篇文章感覺太詳細,有時候一直懷疑是不是失去了算法的本質,不應該寫這麼詳細的文章,而更加精簡一點,但可能和從小記筆記有關,很難改過來了,慢慢改吧!

        最後還是希望文章對你有所幫助,如果文章有不足或錯誤之處,請海涵~

繼續閱讀