李樹濤,胡秋偉
(湖南大學(xué)電氣與信息工程學(xué)院,湖南長(zhǎng)沙 410082)
文獻(xiàn)[1,2]介紹了如何把Matlab引入到“數(shù)字圖像處理”教學(xué)中,Matlab能很方便對(duì)圖像進(jìn)行處理,提高了學(xué)習(xí)效率。筆者認(rèn)為,僅偏重于學(xué)生如何使用Matlab工具箱實(shí)現(xiàn)圖像處理的功能,學(xué)生難以深入理解算法的本質(zhì),不利于學(xué)生深刻理解數(shù)字圖像的各種算法原理。同時(shí),工程應(yīng)用中大多使用C語言及其開發(fā)工具進(jìn)行視頻的采集、處理、傳輸。由于Matlab程序的移植性較差,學(xué)生學(xué)習(xí)完成后不能面對(duì)實(shí)際的開發(fā)應(yīng)用,難以真正提高學(xué)生的工程實(shí)踐動(dòng)手能力。文獻(xiàn)[3]利用VC++開發(fā)相應(yīng)的可視化課件和教學(xué)演示系統(tǒng)進(jìn)行教學(xué),可以加深學(xué)生對(duì)算法原理的理解,增強(qiáng)學(xué)生的動(dòng)手能力。但由于直接利用VC++編寫圖像處理算法難度較大,且對(duì)于復(fù)雜的算法學(xué)生很難編程實(shí)現(xiàn),加大了教學(xué)難度。
為了讓學(xué)生既能掌握基本理論和技術(shù),又能較容易編寫算法的程序,我們?cè)凇皵?shù)字圖像處理”的教學(xué)中引入了OpenCV。該軟件是以C函數(shù)和C++類的形式實(shí)現(xiàn)大量圖像處理算法,學(xué)生可以方便地利用OpenCV進(jìn)行圖像處理算法的編程和驗(yàn)證,進(jìn)而在VC++中開發(fā)功能更強(qiáng)大的應(yīng)用程序。相對(duì)于Matlab而言,學(xué)生不僅可以利用OpenCV開放的源代碼,以函數(shù)進(jìn)行圖像處理,而且可以查看算法的代碼實(shí)現(xiàn),可以較好地培養(yǎng)學(xué)生的編程能力。
OpenCV是Intel公司支持的開源計(jì)算機(jī)視覺庫[4]。它由一系列C函數(shù)和少量C++類構(gòu)成,實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺方面的很多通用算法,可以方便地在VC6.0、VC.net、VS2008等編譯器中使用。OpenCV采用優(yōu)化的C代碼編寫函數(shù),執(zhí)行速度快,注重實(shí)時(shí)圖像處理。其包含的函數(shù)有500多個(gè),涵蓋了計(jì)算機(jī)視覺的許多應(yīng)用領(lǐng)域,如工廠產(chǎn)品檢測(cè)、醫(yī)學(xué)成像、信息安全、用戶界面、攝像機(jī)標(biāo)定、立體視覺和機(jī)器人等,利用這些函數(shù)幾乎可以完成所有圖像處理操作。因?yàn)橛?jì)算機(jī)視覺和機(jī)器學(xué)習(xí)密切相關(guān),所以O(shè)penCV還提供了機(jī)器學(xué)習(xí)庫(MLL)。該機(jī)器學(xué)習(xí)庫側(cè)重于統(tǒng)計(jì)方面的模式識(shí)別和聚類。機(jī)器學(xué)習(xí)庫除了用在視覺相關(guān)的任務(wù)中,還可以方便地應(yīng)用于其他的機(jī)器學(xué)習(xí)場(chǎng)合。應(yīng)用OpenCV能實(shí)現(xiàn)對(duì)圖像數(shù)據(jù)的操作、對(duì)圖像和視頻的輸入輸出、對(duì)矩陣、向量和各種動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)的操作、基本的數(shù)字圖像處理、結(jié)構(gòu)分析、攝像頭標(biāo)定、目標(biāo)識(shí)別以及GUI等功能[5]。
為了使學(xué)生能掌握?qǐng)D像處理的理論知識(shí),以便提高工程實(shí)踐能力。OpenCV的開源性使其成為圖像處理實(shí)踐能力培養(yǎng)的主要手段。我們?cè)诮虒W(xué)中引入了OpenCV的圖像格式轉(zhuǎn)換、邊緣檢測(cè)、圖像分割、直方圖均衡、圖像平滑、距離變換、用 Hough變換檢測(cè)直線、運(yùn)動(dòng)目標(biāo)檢測(cè)與跟蹤和人臉檢測(cè)等案例。本文僅以邊緣檢測(cè)、圖像平滑和人臉檢測(cè)來舉例說明OpenCV在數(shù)字圖像處理教學(xué)中的應(yīng)用。
邊緣檢測(cè)是圖像處理和計(jì)算機(jī)視覺中的基本問題,通過對(duì)圖像上各個(gè)像素點(diǎn)進(jìn)行一階或二階微分來確定邊緣像素點(diǎn)。根據(jù)數(shù)字圖像的特點(diǎn),常用差分代替導(dǎo)數(shù)運(yùn)算,由于一階導(dǎo)數(shù)運(yùn)算具有固定的方向性,只能檢測(cè)特定方向的邊緣。為了克服一階導(dǎo)數(shù)的確定,可以計(jì)算圖像的梯度。圖像梯度的最重要性質(zhì)是:梯度的方向在圖像灰度最大變化率上,它恰恰可以反映出圖像邊緣上的灰度變化。
圖像邊緣提取的常用算子有Robert算子、Sobel算子 、Prewitt算子 、Krisch 算子和Canny 算子等。下面以Canny算子為例,說明OpenCV在數(shù)字圖像處理中邊緣檢測(cè)的實(shí)現(xiàn)。
Canny算法的核心包括下面幾個(gè)步驟:①用高斯濾波器平滑圖像;②用一階偏導(dǎo)的有限差分計(jì)算梯度的幅值和方向;③對(duì)梯度幅值進(jìn)行非極大值抑制;④用雙閾值算法檢測(cè)和連接邊緣;⑤采用高斯平滑函數(shù)。
在傳統(tǒng)的理論教學(xué)中,學(xué)生很難感性理解整個(gè)過程?,F(xiàn)在利用OpenCVVC++編寫程序并一步步調(diào)試,讓學(xué)生看到每一個(gè)中間結(jié)果,同時(shí)也看到整個(gè)算法的代碼實(shí)現(xiàn),使他們不僅明白理論知識(shí),也了解了如何用C和C++去實(shí)現(xiàn)算法。在OpenCV中可以寫出利用Canny算子進(jìn)行邊緣檢測(cè)的代碼:
IplImage*img=cvLoadImage("Lena.jpg",0);
IplImage*result img=cvCreateImage(cvSize(img->width,img->height),IPL DEPTH 8U,1);
cvCanny(img,result img,threshold1,threshold2);
cvNamedWindow("result",CV WINDOW A UTOSIZE);
cvShowImage("result",result img);
上面程序中,第一句利用cvLoadImage函數(shù)加載一幅圖像到結(jié)構(gòu)體變量img中,第二個(gè)參數(shù)0代表把加載的圖像轉(zhuǎn)換成灰度圖像,第二句利用cvCreateImage創(chuàng)建一幅與img同樣大小、通道數(shù)為1的圖像,用于存放邊緣檢測(cè)的結(jié)果。下一句cv-Canny函數(shù)對(duì)img圖像進(jìn)行邊緣檢測(cè),檢測(cè)結(jié)果存放到變量result img中,threshold1和 threshold2中的小閾值用來控制邊緣檢測(cè),大閾值用來控制強(qiáng)邊緣的初始化分割。最后cvNamedWindow創(chuàng)建一個(gè)顯示窗口,cvShowImage用于在窗口上顯示圖片。實(shí)驗(yàn)結(jié)果如圖1所示。
圖1 Canny邊緣檢測(cè)結(jié)果
通過OpenCV對(duì)Canny邊緣檢測(cè)進(jìn)行演示,使得理論算法變得具體和簡(jiǎn)單。相對(duì)于Matlab,利用OpenCV進(jìn)行Canny邊緣檢測(cè)并不復(fù)雜。但由于OpenCV的開源性,學(xué)生可以通過查看cvCanny函數(shù)的源代碼,能更清晰地了解Canny邊緣檢測(cè)的實(shí)現(xiàn)過程,同時(shí)鍛煉了學(xué)生的C語言與C++編程能力。如果在實(shí)際應(yīng)用中碰到邊緣檢測(cè),則可以方便地把代碼移植到應(yīng)用程序中,方便了圖像處理在工程實(shí)際中的應(yīng)用,加強(qiáng)了學(xué)生實(shí)踐動(dòng)手能力的培養(yǎng)。
圖像平滑是一類簡(jiǎn)單但使用頻率很高的圖像處理方法。平滑處理的用途有很多,常用于去除圖像上的噪聲或者減少失真。圖像的常見噪聲主要有加性噪聲、乘性噪聲和量化噪聲等。由于圖像的能量主要集中在低頻部分,而噪聲所在的頻段主要在高頻段,因此通常都是采用低通濾波的方法消除噪聲。
目前OpenCV可以提供五種不同的平滑操作方法,所有操作都由cvSmooth函數(shù)實(shí)現(xiàn),該函數(shù)可以將用戶所期望的平滑方式作為參數(shù),其原型如下:
void cvSmooth(const CvArr* src,CvArr* dst,int smoothtype=CV GAUSSIAN,int param1=3,int param2=0,double param3=0,double param4=0);
參數(shù)smoothtype為CV BLUR NO SCALE、CV BLUR、CV GAUSSIAN 、CV MEDIAN 和 CV BILATERAL,分別代表簡(jiǎn)單不帶尺度變換的模糊、均值濾波、高斯模糊、中值濾波和雙邊濾波。四個(gè)參數(shù)param1,param2,param3和param4的含義取決于smoothtype的值。
圖2給出了OpenCV的均值濾波和中值濾波在圖像平滑中的應(yīng)用示例。圖2(a)是加了強(qiáng)度為0.02椒鹽噪聲的Lena圖像,圖2(b)是用3×3的模板均值濾波后的結(jié)果,圖2(c)是用3×3的模板中值濾波后的結(jié)果。通過OpenCV的實(shí)驗(yàn)演示,可以使學(xué)生看到均值濾波對(duì)椒鹽噪聲只能得到一定程度的抑制,而中值濾波的效果好于均值濾波。
圖2 均值濾波和中值濾波結(jié)果
人臉檢測(cè)是指對(duì)于任意一幅給定的圖像,采用一定的策略對(duì)其進(jìn)行搜索以確定其中是否含有人臉。如果含有人臉,則返回人臉的位置、大小和姿態(tài)。
OpenCV實(shí)現(xiàn)了基于Viola-Jones檢測(cè)器的人臉檢測(cè)技術(shù)[6]。Viola-Jones分類器使用篩選式的級(jí)聯(lián)AdaBoost分類器。級(jí)聯(lián)的每個(gè)節(jié)點(diǎn)使用Ada-Boost來學(xué)習(xí)每個(gè)高檢測(cè)率低拒絕率的多層分類器,使用的是類Haar特征。在OpenCV中使用detect and draw函數(shù)進(jìn)行人臉檢測(cè),在圖中用不同顏色的矩形框畫出人臉的位置。演示結(jié)果如圖3所示。
圖3 人臉檢測(cè)結(jié)果
將OpenCV引入到“數(shù)字圖像處理”教學(xué),由于OpenCV的開源特性,使得學(xué)生可以更清晰地了解算法的實(shí)現(xiàn)過程,加深對(duì)算法的理解。由于OpenCV可以在Visual C++等主流開發(fā)環(huán)境中運(yùn)行,學(xué)生可以方便地開發(fā)功能更豐富的應(yīng)用程序,這既可以提高學(xué)生的學(xué)習(xí)興趣和自信心,也鍛煉了編程能力;由于OpenCV易學(xué)易用,可以利用課程設(shè)計(jì)的機(jī)會(huì)讓學(xué)生自己編寫圖像處理的工程應(yīng)用軟件,而不僅僅局限于用Matlab等工具進(jìn)行仿真實(shí)驗(yàn)。
[1] 黎寧,徐曉波,牛征.Matlab平臺(tái)下圖像處理實(shí)驗(yàn)教學(xué)軟件的實(shí)現(xiàn)[J].南京:電氣電子教學(xué)學(xué)報(bào),2001,23(5):55-56
[2] 張坤華,紀(jì)震.“數(shù)字圖像處理”可視化教學(xué)體系探索[J].南京:電氣電子教學(xué)學(xué)報(bào),2007,29(1):113-115
[3] 盛利元,李宏言,孫克輝.“數(shù)字圖像處理”實(shí)驗(yàn)教學(xué)探索與實(shí)驗(yàn)軟件研[J].南京:電氣電子教學(xué)學(xué)報(bào),2005,27(3):75-77
[4] Gary Bradski,Adrian Kaebler.Learing OpenCV[M].南京:東南大學(xué)出版社,2009
[5] 劉瑞禎,于仕琪.OpenCV教程[M].北京:北京航空航天大學(xué)出版社,2008
[6] P.Viola and M.Jones.Rapid Object Detection Using a Boosted Cascade of Simple Features[C].IEEE CVPR,2001:1-8