羅志高 王變琴



摘要:利用OpenCV開(kāi)源庫(kù)對(duì)圖像進(jìn)行邊沿檢測(cè)、灰度化等一系列操作,得到圖像對(duì)應(yīng)的特征像素矩陣,再通過(guò)RESTful方法實(shí)現(xiàn)數(shù)據(jù)傳輸、存儲(chǔ),便于后續(xù)操作。實(shí)現(xiàn)了文件讀取、邊沿識(shí)別、矩陣獲取等功能的圖形化界面操作。
關(guān)鍵詞:圖像處理;邊沿檢測(cè);MFC;OpenCV;Visual Studio
中圖分類號(hào):TP274 ? ? ? ? ?文獻(xiàn)標(biāo)識(shí)碼:A
數(shù)字圖像處理是指通過(guò)計(jì)算機(jī)對(duì)圖像進(jìn)行去噪聲、增強(qiáng)、復(fù)原、分割、提取特征等一系列處理的方法和技術(shù)。由于數(shù)字圖像的組成實(shí)質(zhì)上是一個(gè)二維矩陣,數(shù)字圖像處理是對(duì)二維矩陣進(jìn)行相關(guān)操作。數(shù)字圖像處理過(guò)程:圖像獲取、圖像增強(qiáng)、圖像濾波、灰度化、邊沿檢測(cè)、圖像分割、圖像壓縮編碼、圖像復(fù)原、圖像重建[1]。
OpenCV是一個(gè)基于C/C++語(yǔ)言的開(kāi)源圖像處理函數(shù)庫(kù),它具有的諸多特性使其成為圖像處理研究者的首選工具。
1 系統(tǒng)的架構(gòu)設(shè)計(jì)
數(shù)字圖像技術(shù)涵蓋方方面面,本文主要通過(guò)VS(Visual Studio)的MFC編程,實(shí)現(xiàn)一個(gè)具有圖像動(dòng)態(tài)讀取、處理、保存和顯示[2]等功能的系統(tǒng)。整個(gè)系統(tǒng)包括文件操作、邊沿檢測(cè)、特征提取及查詢3個(gè)模塊及其子模塊,如圖1所示。
1.1 文件操作設(shè)計(jì)
動(dòng)態(tài)選擇所需的圖像文件,放至指定的數(shù)據(jù)結(jié)構(gòu)或相應(yīng)控件,便于進(jìn)一步處理。在處理完成之后,可以把所需存儲(chǔ)的文件以指定格式存儲(chǔ)至指定位置,便于之后查閱。
1.2 邊沿檢測(cè)設(shè)計(jì)
先將原彩圖進(jìn)行灰度化,轉(zhuǎn)換為黑白圖,然后把圖像縮放至固定窗口,以便于用戶可以在同一界面查看原圖與處理后的圖像對(duì)比。然后利用Sobel邊沿檢測(cè)算子檢測(cè)出圖像邊沿,并展示至特定位置。同時(shí)根據(jù)效果。自行嘗試調(diào)節(jié)閾值得到最佳的邊沿圖像。
1.3 特征提取及查詢?cè)O(shè)計(jì)
在圖像處理之后,會(huì)得到處理后的圖像的矩陣信息,然后點(diǎn)擊查詢按鈕,連接遠(yuǎn)程服務(wù)器,比對(duì)存儲(chǔ)在服務(wù)器中的數(shù)據(jù),將信息比較接近的圖片鏈接傳回,直接訪問(wèn)返回的鏈接,查看系統(tǒng)返回的圖片是否為自己所需。
1.4 圖像處理系統(tǒng)界面設(shè)計(jì)
采用單一對(duì)話框,所有的東西都集成在一個(gè)界面,包含打開(kāi)文件、保存、查詢等按鈕,全都是圖形界面交互,便于用戶操作。
2 數(shù)字處理系統(tǒng)實(shí)現(xiàn)
2.1 文件操作模塊的實(shí)現(xiàn)
文件讀、寫、增、刪操作在計(jì)算機(jī)系統(tǒng)中具有相當(dāng)重要的作用。操作系統(tǒng)本身就存儲(chǔ)在文件中,在系統(tǒng)啟動(dòng)過(guò)程中加載到內(nèi)存中,自動(dòng)運(yùn)行,所涉及的圖像、文檔、應(yīng)用程序等都是以文件形式存儲(chǔ)到系統(tǒng)中的。
2.2 控件類實(shí)現(xiàn)文件操作
在MFC開(kāi)發(fā)中,所有的操作都是對(duì)控件添加響應(yīng)函數(shù)實(shí)現(xiàn)的,而要實(shí)現(xiàn)文件打開(kāi),即對(duì)“瀏覽”按鍵添加一個(gè)函數(shù)響應(yīng)。在MFC中,已經(jīng)集成了一個(gè)類CFileDialog可以實(shí)現(xiàn)對(duì)話框操作,這個(gè)函數(shù)如圖2所示。
CFileDialog類型的函數(shù)dlg,可以實(shí)現(xiàn)對(duì)Windows文件操作的對(duì)話框,如圖2所示,該函數(shù)的參數(shù)意思表示該對(duì)話框是打開(kāi)文件還是保存文件,true意味著該對(duì)話框?yàn)榇蜷_(kāi)文件操作,false表示該操作是保存文件的對(duì)話框。文件的默認(rèn)擴(kuò)展名,如想打開(kāi)jpg文件,則在對(duì)話框中默認(rèn)顯示jpg類型的文件或是在保存時(shí)候默認(rèn)保存為jpg格式的文件。要打開(kāi)的目標(biāo)文件名,可不指定文件擴(kuò)展名,不指定則默認(rèn)用第二個(gè)參數(shù)指定的擴(kuò)展名。表示目標(biāo)文件的狀態(tài),OFN_FILEMUSTEXIST表示目標(biāo)必須存在,OFN_HIDEREADONLY不顯示只讀文件。過(guò)濾文件類型,如只顯示jpg或bmp格式文件,可自行選擇。
獲取文件路徑,如圖3所示,可以用DoModal函數(shù),當(dāng)用戶選定之后,用CFileDialog自帶的構(gòu)造函數(shù)GetPathName獲取路徑、文件名和擴(kuò)展名。就可以獲取所需要的文件,進(jìn)行后續(xù)操作。同時(shí)用SetWindowText函數(shù)將路徑寫入文本控件,以便看到文件路徑等相關(guān)信息。
2.3 邊沿檢測(cè)模塊的實(shí)現(xiàn)
圖像的縮放就是把圖像按照比例進(jìn)行特定的大小變換,為了使用戶在使用時(shí)能夠有更好的體驗(yàn),更加直觀地對(duì)比原圖像與處理后的圖像,把圖像限定在特定的區(qū)域。而每一幅圖像的大小都不一樣,對(duì)每一幅需要處理的圖像進(jìn)行長(zhǎng)和寬的變換,使其能夠適應(yīng)展示窗口。如限定圖像展示區(qū)域的寬(L)和高(H)為400×245,假定每一幅圖像的寬、高分別為X、Y,需要算出變換的系數(shù)S1、S2,則有如下表達(dá)式:
實(shí)際處理時(shí),通過(guò)中間S1、S2表達(dá)式先求出系數(shù)S1、S2,然后根據(jù)后面表達(dá)式,就可以把圖像轉(zhuǎn)換成為特定大小的圖像了。由于需要把圖像固定在特定窗格,并放置于正中,還需要獲取圖像的位置,因此需要計(jì)算圖像在左上角的期望坐標(biāo)作為原始坐標(biāo),以此進(jìn)行圖像拓展,即可把圖像完整地縮放至特定的顯示窗格了,更加便于查看。邊沿檢測(cè)流程如圖4所示。
通過(guò)上述流程,即可得到邊沿檢測(cè)后的圖像。
2.4 圖像的灰度化
要實(shí)現(xiàn)把彩色圖像轉(zhuǎn)變?yōu)橛闪涟当硎镜暮诎讏D,就需要了解彩圖的組成,最常用的彩色圖像格式有RGB、HSV、HLS等幾種。定義于RGB空間的彩圖,每個(gè)像素點(diǎn)由R、G、B 3個(gè)分量組成,分別代表紅、綠、藍(lán)。每個(gè)分量取不同的值,組合成的像素點(diǎn)就呈現(xiàn)出不同的顏色,多個(gè)像素點(diǎn)的組合就構(gòu)成了一幅彩圖,常見(jiàn)的24深度彩圖,每個(gè)像素點(diǎn)的每個(gè)分量取值為0~255。HSV顏色模型的3個(gè)參數(shù)分別是色調(diào)、飽和度、亮度,是一種比較直觀的顏色模型,可轉(zhuǎn)換為RGB彩圖。HLS模型參數(shù)跟HSV類似,不過(guò)HLS是目前工業(yè)界的標(biāo)準(zhǔn),比HSV更為強(qiáng)大,幾乎包括了目前人類所能感知的顏色,同樣可以轉(zhuǎn)換為RGB圖像。因此,研究RGB圖像灰度化即可得到其他圖像的灰度化方法,而對(duì)RGB圖像灰度化,即對(duì)RGB 3個(gè)分量轉(zhuǎn)為1個(gè),最終得到由亮暗表示的灰度值。常見(jiàn)的方法如下:
1)Gray=B;Gray=G;Gray=R;
2)Gray=max(B+G+R);
3)Gray=(B+G+R)/3;
4)Gray=0.072169B+0.715160G+0.212671R;
5)Gray=0.11B+0.59G+0.3R。
方法一,用RGB分量的隨便一個(gè)值作為該點(diǎn)的灰度;方法二,選取3個(gè)分量中最大的作為灰度;方法三,求取3個(gè)分量的平均值作為灰度值;方法四與方法五都是根據(jù)相應(yīng)特性對(duì)3個(gè)分量進(jìn)行加權(quán)平均,方法五的權(quán)值是從生理學(xué)的角度,即人眼對(duì)顏色的敏感度得出,方法四則是OpenCV所采用的加權(quán)值。我們基于OpenCV進(jìn)行的圖像處理,當(dāng)然就是用的方法四,即通過(guò)VS內(nèi)置函數(shù),獲取圖像3個(gè)分量的大小,然后設(shè)定灰度值Y。根據(jù)方法四,算出灰度值Y,然后渲染,即可把彩圖轉(zhuǎn)換為用亮暗表示的灰度圖了。
2.5 基于一階導(dǎo)數(shù)的邊沿檢測(cè)
邊沿檢測(cè)是圖像處理重要的環(huán)節(jié),需要按照以下步驟獲取邊沿圖像。
①需要對(duì)圖像進(jìn)行灰度化,這個(gè)步驟已經(jīng)在上一步實(shí)現(xiàn)了。由于圖像通常都會(huì)受到無(wú)關(guān)信息的干擾,因此需要對(duì)圖像進(jìn)行濾波處理,用于消除圖像中的隨機(jī)噪聲。鑒于本系統(tǒng)是基于OpenCV實(shí)現(xiàn)的,因此需要了解一下OpenCV所采用的高斯濾波。
②高斯濾波的實(shí)現(xiàn),就是采用一個(gè)矩陣模板進(jìn)行加權(quán)運(yùn)算。舉個(gè)例子,八連通區(qū)域的圖像,中間點(diǎn)的像素值就等于八連通區(qū)域像素值的均值,以達(dá)到平滑的效果,該矩陣模板就是常說(shuō)的高斯核。假定高斯核維數(shù)為(2k+1)×(2*+1),則離散高斯核的矩陣計(jì)算如下:
③得到濾波后的圖像之后,就可利用一階偏導(dǎo)的有限差分來(lái)計(jì)算梯度的幅值和方向了。一般來(lái)說(shuō),獲取灰度圖梯度可用有限差分近似,然后得到圖像在X、Y方向上偏導(dǎo)數(shù)的兩個(gè)矩陣,叫做梯度算子。常用的梯度算子有Roberts算子、Sobel算子、Prewitt算子、Canny算子。本文采用的是Canny算子,Canny算法選取的卷積算子根據(jù)實(shí)際情況可以隨意調(diào)整,采用的是三維,其實(shí)采用的是Sobel算子,因?yàn)镾obel算子對(duì)灰度漸變和噪聲較多的圖像處理效果較好。矩陣表達(dá)式如下:
由上式求得矩陣后,即可進(jìn)對(duì)梯度幅值進(jìn)行非極大值抑制。顧名思義,非極大值抑制就是把不是極大值的像素點(diǎn)視為不存在,即為0,把極大值突出體現(xiàn),記為1,由此得到一個(gè)二值化矩陣。問(wèn)題就轉(zhuǎn)換為如何確定極大值,很顯然,需要比較每個(gè)像素點(diǎn)的灰度值與其領(lǐng)域像素點(diǎn)的灰度值,通常比較四領(lǐng)域或八領(lǐng)域。在上一步求偏導(dǎo)的過(guò)程中,已經(jīng)得到了梯度的方向,因而只需比較該方向上的領(lǐng)域像素點(diǎn)的大小即可,若該點(diǎn)為極大值,則記為1,否則,幅值為0。
④上一步之后,邊沿的地方基本都變?yōu)?,其他地方變?yōu)?,邊沿圖像近在眼前。然而實(shí)際操作中,噪聲的去除卻不是那么完善,極大值確定也有可能判斷不出,導(dǎo)致出現(xiàn)很多假邊沿,需要進(jìn)一步處理,以得到更為接近真實(shí)邊沿的邊沿圖像,這就是邊沿檢測(cè)的最后一步,用雙閾值算法檢測(cè)和連接邊沿,也是Canny算法比較優(yōu)于其他算法的地方。
雙閾值算法把先滿足高閾值的像素點(diǎn)連接起來(lái),如果不閉合,則把部分與高閾值鄰域且滿足低閾值的像素點(diǎn)連接起來(lái),最后把選出來(lái)的這些像素點(diǎn)連接起來(lái),就得到邊沿檢測(cè)圖了。本文的開(kāi)發(fā)是基于OpenCV開(kāi)源庫(kù)的一個(gè)應(yīng)用軟件,通過(guò)有效利用資源,OpenCV已經(jīng)幫我們封裝了一個(gè)函數(shù),可以完成上述的進(jìn)程。這個(gè)函數(shù)是vCanny(constCVArr* image,CVArr* edges,double threshold1,double threshold2,intaperture_size=3)。各參數(shù)含義如下:image,單通道輸入圖像,待處理圖像的灰度圖;edges,單通道輸出圖像,得到的邊沿檢測(cè)圖;threshold1,閾值1,較低的閾值;threshold2,閾值2,較高的閾值;aperture_size,內(nèi)核算子的維度,OpenCV采用的算子是Sobel算子,故該值為3。因此只需要把原圖像轉(zhuǎn)變?yōu)榛叶葓D之后調(diào)用該函數(shù),即可得到灰度圖,同時(shí)閾值可以機(jī)動(dòng)調(diào)節(jié),代碼如圖5所示。
多次結(jié)果證明,低閾值與高閾值的比例在1:2至1:3之間得到的圖像效果最好。至此邊沿檢測(cè)完成。
3 矩陣信息提取模塊的實(shí)現(xiàn)
OpenCV中圖像與矩陣的轉(zhuǎn)換:就是把圖像對(duì)應(yīng)的像素點(diǎn)用矩陣描述出來(lái)。在OpenCV中,已經(jīng)存在這樣一個(gè)庫(kù)函數(shù),直接調(diào)用即可。庫(kù)函數(shù)如下。
cvCreateMat(param1,param2,param3)
param1:矩陣的行數(shù),通常用*->width,以滿足不同大小的圖片;
param2:矩陣的列數(shù),通常用*->height,以滿足不同尺寸的圖片;
param3:矩陣元素類型,通常以CV_<比特?cái)?shù)>(S|U|F)C<通道數(shù)>型式描述。
然后直接調(diào)用該函數(shù),就可以把圖片轉(zhuǎn)換成矩陣形式了。
二值化圖像矩陣:可以把邊沿檢測(cè)圖轉(zhuǎn)化為矩陣,作為存儲(chǔ)依據(jù),這也是最優(yōu)的方案。但本文沒(méi)有這樣做,主要是考慮到執(zhí)行順序、效率和界面美觀。倘若用邊沿檢測(cè)圖直接轉(zhuǎn)化矩陣,則需要在邊沿檢測(cè)圖完成之后,再次觸發(fā),就必須在界面重新設(shè)置一個(gè)能夠使其響應(yīng)的控件,影響界面美觀;若置于同一響應(yīng)函數(shù),又需要考慮先后問(wèn)題。因此,本文采用灰度化后的圖片,將其與閾值調(diào)節(jié)放置于同一響應(yīng)函數(shù),并發(fā)執(zhí)行。實(shí)現(xiàn)如圖6所示。
利用CV_MAT_ELEM函數(shù)把矩陣的每一個(gè)元素提取出來(lái),然后做判斷,高于某值的設(shè)為1,低于某值的設(shè)為0,即可獲得二值化矩陣。
4 信息查詢模塊的實(shí)現(xiàn)
4.1 VS網(wǎng)絡(luò)請(qǐng)求的實(shí)現(xiàn)
VS的MFC發(fā)起網(wǎng)絡(luò)請(qǐng)求與大部分網(wǎng)絡(luò)請(qǐng)求一樣,利用RESTful框架,即通常所說(shuō)的HTTP請(qǐng)求,包括GET和POST兩種方式。實(shí)現(xiàn)過(guò)程即調(diào)用HTTP請(qǐng)求或相應(yīng)相關(guān)函數(shù),需要注意參數(shù)的類型與GET或POST請(qǐng)求的吻合,以及URL的正確性。
4.2 信息展示
把從網(wǎng)頁(yè)查詢得到的數(shù)據(jù),通過(guò)JSON傳回,解析之后,顯示在對(duì)應(yīng)的控件中。為了便于查看,需要在服務(wù)器端進(jìn)行信息比對(duì),如果有相似信息圖片,則把對(duì)應(yīng)URL或搜索關(guān)鍵字進(jìn)行展示,否則提示不存在。系統(tǒng)整體實(shí)現(xiàn)效果如圖7所示
如圖7所示,a為原圖像,b為縮小后放至固定大小控件中的圖像。原圖像尺寸為800×600,經(jīng)過(guò)變換,變?yōu)檫m應(yīng)窗口大小的400×245,效果十分明顯[3]。
5 結(jié)語(yǔ)
綜上所述,本文主要研究了數(shù)字圖像處理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn),選用了VS 2015開(kāi)發(fā)界面,為用戶提供了一個(gè)數(shù)字圖像處理的GUI平臺(tái),對(duì)圖像處理方法進(jìn)行研究,包括圖像的縮放,灰度變換,濾波處理,邊沿檢測(cè)及矩陣提取等使用OpenCV庫(kù),利用VS 2015開(kāi)發(fā)了一套包含文件讀取、邊沿檢測(cè)、矩陣提取等功能的數(shù)字圖像處理系統(tǒng),界面友好,對(duì)用戶沒(méi)有專業(yè)門檻限制,對(duì)話框基本滿足用戶使用需求,同時(shí)有很強(qiáng)的拓展性。
參考文獻(xiàn)
[1] 陳天華.數(shù)字圖像處理[M].北京:清華大學(xué)出版社,2007.
[2] 常奇峰.基于VC++的數(shù)字圖像處理軟件開(kāi)發(fā)[D].南京:南京航空航天大學(xué),2010.
[3] 賀東霞,李竹林,王靜.淺談數(shù)字圖像處理的應(yīng)用與發(fā)展趨勢(shì)[J].延安大學(xué)學(xué)報(bào)(自然科學(xué)版),2013,32(12):18-21.