汪 沛
(北京林業(yè)大學(xué)電子信息科學(xué)與技術(shù)系,北京 100083)
傳統(tǒng)的C語言教學(xué)偏重于讓學(xué)生從熟悉基本概念和規(guī)則開始,逐漸過渡到簡單算法的編程實現(xiàn)和程序設(shè)計開發(fā),最終熟悉和掌握C語言程序設(shè)計的技巧。這種教學(xué)方法從基礎(chǔ)的知識元素開始學(xué)習(xí),然后將這些元素組合開發(fā)出具有特定功能的程序。其特點是由點及面,但由于最初較長時間的基礎(chǔ)規(guī)則學(xué)習(xí),學(xué)生會感覺比較枯燥。
由于圖像處理具有直觀、形象和生動的特點,因此筆者提出在“高級語言程序設(shè)計”的授課中基于OpenCV庫開發(fā)程序,先讓學(xué)生感受C語言編程的強大功能,以提高學(xué)生的興趣,然后再剖析程序,向?qū)W生解釋講授各個知識點。OpenCV是Intel公司開發(fā)的開源計算機視覺庫,包含了大量的圖像處理、結(jié)構(gòu)分析、運動分析和目標(biāo)跟蹤等相關(guān)函數(shù)[1]。學(xué)生能夠基于OpenCV庫中的函數(shù),較快進行相關(guān)領(lǐng)域的二次開發(fā)。
為增強教學(xué)過程中學(xué)生的興趣,筆者選取一張功夫熊貓的圖片作為實驗中所用的處理圖像。為了方便后續(xù)處理,利用OpenCV庫中的cvCvtColor函數(shù)將彩色圖像轉(zhuǎn)換為灰度圖像。
在本次教學(xué)中,擬基于OpenCV庫中的函數(shù)實現(xiàn)兩類圖像處理操作:圖像翻轉(zhuǎn)操作和圖像邊緣檢測操作。通過向?qū)W生展示兩類操作所得到的處理結(jié)果,進一步提高學(xué)習(xí)興趣,同時向?qū)W生強調(diào)C語言中如下一些關(guān)鍵概念并深化理解:①數(shù)組的操作;②函數(shù)的操作;③指針作為函數(shù)參量的應(yīng)用;④結(jié)構(gòu)體變量的使用及成員訪問。
在C語言中,圖像大多用數(shù)組來表示,灰度圖像是用二維數(shù)組表示,彩色圖像是用三維數(shù)組來表示。圖像的翻轉(zhuǎn)則可以看成是數(shù)組元素的位置調(diào)換;而圖像邊緣檢測則是依照一定的規(guī)律尋找數(shù)組元素中的特定信息。
由于采用了OpenCV庫,因此圖像處理的整個過程中更是貫穿函數(shù)的概念。彩色圖像至灰度圖像的轉(zhuǎn)換、圖像垂直或者水平翻轉(zhuǎn)、以及圖像邊緣檢測都是用函數(shù)來完成。函數(shù)的調(diào)用使主函數(shù)的結(jié)構(gòu)清晰,各個部分一目了然。
在C語言中,有多種方法可以在主函數(shù)和圖像操作函數(shù)之間傳遞數(shù)組元素信息,OpenCV庫函數(shù)中采用的是指針的方式。指針的訪問方式具有形式靈活和效率高的特點。
在OpenCV中最重要的結(jié)構(gòu)體是IplImage結(jié)構(gòu),主要用于圖像處理方面。IplImage結(jié)構(gòu)來自于Intel Image Processing Library,OpenCV只支持其中的一個子集[2]。IplImage結(jié)構(gòu)中包含了圖像大小、寬度、高度和像素位深度等信息,這些成員信息都可以在程序中進行訪問和輸出。
由上述分析不難發(fā)現(xiàn),這些C語言中的關(guān)鍵概念在本次教學(xué)方案中都有所涉及。通過上述形象生動的圖像變換操作,學(xué)生會對這些概念有非常深的印象,這時輔以說明和引導(dǎo)可以使學(xué)生加深理解。
利用OpenCV庫中的cvFlip函數(shù),圖像可以非常容易實現(xiàn)垂直翻轉(zhuǎn)、水平翻轉(zhuǎn)和垂直又水平翻轉(zhuǎn)。cvFlip函數(shù)的具體說明如下:

其中,src代表原數(shù)組;dst是目標(biāo)數(shù)組,如果dst=NULL表示翻轉(zhuǎn)是在內(nèi)部替換;flip_mode是指定如何翻轉(zhuǎn)數(shù)組,flip_mode=0表示沿X軸翻轉(zhuǎn),flip_mode>0表示沿Y軸翻轉(zhuǎn),flip_mode<0表示沿X軸后沿Y軸翻轉(zhuǎn)。
利用cvFlip函數(shù)實現(xiàn)圖像垂直翻轉(zhuǎn)結(jié)果見圖1,其中(a)為原始圖像,(b)為垂直翻轉(zhuǎn)后的圖像。

圖1 原始圖像和翻轉(zhuǎn)圖像
同樣,我們利用OpenCV庫中的cvSobel函數(shù)、cvCanny函數(shù)和cvLaplace函數(shù),可以在圖像中分別實現(xiàn)Sobel、Canny和Laplacian三種算子的邊緣檢測,三個函數(shù)說明如下:

圖2是三種不同算子的邊緣檢測結(jié)果。由結(jié)果可以很容易知道,當(dāng)采用不同的邊緣檢測方法時,所得到的結(jié)果是迥然不同的。而OpenCV的輔助文檔中有對這三個函數(shù)的具體使用說明和三種算子的具體描述。三種邊緣檢測方法都不復(fù)雜,因此可以引導(dǎo)學(xué)生自己查詢文檔和研究算法,并嘗試讓學(xué)生自己編寫三種邊緣檢測方法的函數(shù)。

圖2 邊緣檢測結(jié)果
通過對指向原始圖像和各處理結(jié)果的IplImage結(jié)構(gòu)體指針變量中的各成員變量進行訪問,可以在程序中實時獲取各個圖像的相關(guān)信息[3]。如通過下述語句輸出原圖像的幾個重要信息:

在上述這段程序中,首先通過cvLoadImage函數(shù)打開名為gongfupanda的jpg格式彩色圖片。隨后通過IplImage結(jié)構(gòu)體中的成員變量輸出相關(guān)信息。在程序中,對成員變量的訪問采用了兩種形式,需要讓學(xué)生注意兩種形式的差異和特點。
除了前文中所談及的函數(shù),程序中還使用cvCreateImage函數(shù)創(chuàng)建頭并分配數(shù)據(jù);使用cvN-amedWindow函數(shù)創(chuàng)建顯示窗口;使用cvShowImage函數(shù)在指定窗口中顯示圖像;使用cvReleaseImage函數(shù)釋放頭和圖像數(shù)據(jù)。此處,舉例顯示原始圖像的相關(guān)代碼如下:

其中,CV_WINDOW_AUTOSIZE表示用戶不能手動改變窗口大小,窗口大小會自動調(diào)整以適合要顯示的圖像。顯然,基于OpenCV庫函數(shù)的程序結(jié)構(gòu)非常簡潔。針對程序特點可以推薦學(xué)生采用函數(shù)完成特定功能,實現(xiàn)模塊化設(shè)計的編程思維。
由于OpenCV的開源特性,學(xué)生可以查詢到其中很多庫函數(shù)的實現(xiàn)算法甚至源碼,比較適合學(xué)生在課程結(jié)束之后進一步自學(xué)。OpenCV的開源特性也使得其在工業(yè)界得到了廣泛的青睞,因此學(xué)生對OpenCV的學(xué)習(xí)也可以直接提高實戰(zhàn)能力、縮短與企業(yè)用人需求的對接時間。
本文通過采用開源的OpenCV庫函數(shù)來實現(xiàn)對圖像的翻轉(zhuǎn)以及邊緣檢測操作,能夠增加學(xué)生對學(xué)習(xí)C語言的興趣,同時又將C語言的多種關(guān)鍵知識點融入其中,從而達到寓教于樂的目的。此外,OpenCV具有非常強的實用性,能夠提升學(xué)生解決實際問題的能力,有效增強編程實力,為以后的繼續(xù)學(xué)習(xí)深造和就業(yè)夯實C語言編程基礎(chǔ)。
[1]Gary Bradski,Adrian Kaebler.Learning OpenCV[M].南京:東南大學(xué)出版社,2009年
[2]劉瑞禎,于仕琪.OpenCV教程[M].北京:北京航空航天大學(xué)出版社,2007年
[3]陳勝勇,劉盛.基于OpenCV的計算機視覺技術(shù)實現(xiàn)[M].北京:科學(xué)出版社,2008年.