李志,陳入云
(廣東海洋大學 數學與計算機學院,廣東湛江 524088)
數字圖像處理是目前信息類專業普遍開設的一門專業方向課。其理論深奧、實踐性強,需要較好的算法理解能力和編程能力。通常,在大學開設該課程都會配置部分實驗課時,而實驗課的算法實現以及理論課的效果演示多采用MATLAB[1-2]。
近年來,Python 作為一種免費開源的編程語言,越來越受歡迎。在數字圖像處理方面Python 也有一些功能強大的擴展庫,且在相關聯的深度學習等方面具有很大的優勢。目前,Python 在圖像處理領域的使用變得越來越普及,以Python 語言作為實驗教學中的編程語言,已在一些院校得到應用[3-4]。
Python 與MATLAB 都是解釋型的語言,語法簡單,都能高效地進行數值計算,都支持矩陣和向量運算。在圖像處理方面,MATLAB 有強大的圖像處理工具箱,而Python 也有相應的功能強大的擴展庫。不管是利用現成的函數,還是自編代碼完成圖像處理任務,Python 都能輕松勝任。
Python 是開源免費的程序語言,圍繞其開發的大多數擴展庫都遵循開源的協議,使用成本小。學習者還可以通過學習源碼,加深對原理和算法的理解,有效提高編程能力和代碼質量。而MATLAB 是收費軟件,且大多數函數的底層是封裝起來的,使用者不能接觸實際的實現代碼。
Python 語言處理圖像可以用到的擴展庫有Numpy、Matplotlib、Pillow、Scikit-mage、OpenCV。這些擴展庫能極大地簡化圖像處理的工作。
Numpy 庫提供基本的矩陣和數組運算,及各種數學函數。還提供了傅里葉變換的模塊fft。
對圖像處理而言,Matplotlib 庫主要提供顯示圖像的功能,方便顯示多子圖以及圖像標注。
Pillow 提供了基本的圖像讀取、顯示、寫入、幾何變換、基本圖形繪制、濾波、增強、顏色轉換、形態學操作等的相關函數或方法。
Scikit-image 常簡稱為Skimage,用Numpy 數組表示圖像數據,提供眾多功能模塊,可媲美MATLAB 的圖像處理工具箱。
OpenCV 是跨平臺的計算機視覺和機器學習軟件庫。由C/C++開發,提供了Python 接口。相對Skimage,OpenCV 更強大,可實現工業級的應用。
要滿足數字圖像處理的教學需要,可以使用Numpy 搭配Skimage,或者Numpy 搭配OpenCV。如果配合Jupyter notebook 一起使用,需導入Matplotlib 庫,方便顯示圖像。
Python 代碼可以方便地形成獨立的可執行文件,并兼容多種操作系統。Python 還是面向對象的通用程序開發語言,除了數值計算,也是目前人工智能、深度學習、數據分析等方面使用最多的語言。而數字圖像處理與人工智能等的聯系日益緊密[5-6],在圖像處理中使用Python 替代MATLAB 將有很大的優勢。
為了使學生理解圖像處理的各種算法,了解算法的效果,掌握相關函數的用法,必須在教學中多做演示,并合理地安排實驗內容。以下是筆者在教材Rafael C. Gonzalez 等著的《Digital Image Processing》中用Python 實現的實驗內容。其中一部分作為上課時的演示內容,一部分作為實驗課的實踐環節。
Python 使用Numpy 數組表示圖像數據,對圖像的處理就是對Numpy 數組的操作。而Matplotlib、Pillow、Skimage、OpenCV 都支持Numpy,都有讀寫顯示圖像的函數。
直接灰度變換就是對圖像數據的Numpy 數組的運算。Pillow 的ImageOps 模塊中的函數equalize()可實現直方圖均衡化。Skimage 的exposure 模塊中的equalize_hist()、match_histograms()分別用于實現直方圖均衡化和直方圖匹配。OpenCV 中,使用calcHist()計算直方圖,equalizeHist()函數實現直方圖均衡化。
Pillow 庫中圖像對象的filter()方法或其ImageFilter模塊提供的濾波器方法可實現空域濾波。Skimage 的filters 模塊有大量的空域濾波函數,OpenCV 也提供了大量的空域濾波函數。
Python 中Numpy 的fft 模塊用于實現快速傅里葉變換相關的運算。OpenCV 中的dft2()和idft2()用于實現快速傅里葉變換和反變換。
頻域濾波包括低通濾波、高通濾波、帶通濾波、帶阻濾波、同態濾波等。與MATLAB 一樣,Python 沒有提供頻域濾波的現成的函數,可簡單地使用Numpy 的數組運算和fft 模塊實現。
圖像復原包括去噪和退化圖像的恢復。去噪可用空域濾波或頻域濾波實現。退化圖像的恢復主要包括逆濾波、維納濾波、約束最小二乘方濾波等方法。Skimage 的restoration 模塊提供了均值濾波、雙邊濾波、總變差去噪、小波去噪、維納濾波等函數。也可根據算法原理直接編程實現逆濾波、維納濾波。
離散余弦變換可使用Scipy 的fft 模塊下的dct、idct、dctn、idctn 等函數,也可以使用OpenCV 下的dct、idct 函數。哈達瑪變換可利用Scipy 的linalg 模塊下的hadamard 函數產生哈達瑪矩陣。小波變換可使用PyWavelets 軟件包實現。
形態學處理是圖像預處理和特征提取的重要工具。Skimage 的morphology 模塊中用于形態學操作。OpenCV 中也提供了相應的函數。
圖像分割主要包括邊緣檢測、閾值分割、分水嶺算法、聚類與超像素分割等方法。
Skimage 的filters 模塊包含了邊緣檢測算子和閾值分割的功能;segmentation 模塊包含了分水嶺算法、聚類與超像素分割等算法,以及活動輪廓分割、隨機walker 分割等算法。此外,transform 模塊中還包含了Hough 變換的相關函數,可以檢測直線、圓、橢圓等。OpenCV 中同樣有眾多的函數可實現上述功能。
Skimage 的feature 模塊包含了查找斑點、canny 邊緣檢測、多種角點檢測、灰度共生矩陣、紋理特征、梯度直方圖等的函數。OpenCV 中除實現上述功能的函數外,還包含實現MSER、SIFT、SURF 以及ORB 等特征檢測的函數。
為了提高學生的學習能力及綜合應用能力,應給學生安排一些有實際應用背景的問題,如人像的自動背景虛化、自動校正印刷品圖片的畸變、逆光攝影中的人臉檢測及增強等。這些問題有一定難度,可以讓學生分組協作,作為課程設計的內容,并作為總評成績的一部分,以對學生進行更全面的評價。
Python 是面向對象的程序語言,相對MATLAB 而言學習難度稍大,在一些使用習慣上也有不同。筆者在近幾年的教學中,同時使用這兩種語言作為實驗語言,總結了一些注意事項。
學生應已學習過Python 的基本語法,以及Numpy和Matplotlib,這樣在實驗中只需逐步學習使用Skimage、OpenCV 等擴展庫即可。
在教學中,考慮到學生的實際編程基礎,應允許學生在Python 和MATLAB 中自行選擇,教師同時提供不同語言的實驗內容指導。
圖像處理中需要用到大量現成的函數,部分學生對此不熟悉。但學習現成函數的用法不應是實驗課的重心,這些可以提供資料讓學生自學,教學的重心是引導學生理解算法原理并形成一定的實際應用能力。
所以,為了加深學生對算法原理的理解,提高學生的動手能力,降低學生對現成函數的依賴,應有意識地安排部分圖像處理任務由學生自己編程完成。如直接灰度變換、直方圖均衡化、圖像的空域濾波、頻域濾波、逆濾波、維納濾波、偽彩色處理、Huffman 編碼、算術編碼、邊緣提取等,其中難度較大的可設為選做。
MATLAB 中使用函數imshow()顯示圖像,能自適應地顯示多種格式圖像。
Matplotlib 的pyplot 模塊(簡記為plt)中的imshow( )函數默認將灰度圖像顯示為偽彩色圖像,需要添加參數cmap='gray'才能顯示為灰度圖像,且其顯示亮度是經過拉伸的,并非其真實亮度。
Skimage 的io 模塊中imshow()函數可以正常顯示灰度圖像,且不會自動將其灰度范圍拉伸。但當圖像數據是實數時,其值若超出[0,1],則顯示為偽彩色圖像。
Numpy 中將圖像數據由實數類型轉換為uint8時,是按截斷處理的,如256,257 經轉換后會變成0,1。所以,圖像數據img 轉換為uint8 前,需先執行img[img<0]=0; img [img>255]=255,以得到正確范圍的轉換。
筆者在近三年的數字圖像處理的教學中改用Python 作為實驗語言,經逐步摸索總結,取得了較好的教學效果。主要體現為以下幾點:
(1)Python 的編程效率高,代碼量少,使用相關的模塊能簡單地完成各種復雜的圖像處理任務。沒有對應的現成函數時,也能指導學生根據算法原理編程完成。使用Python 能很好地完成實驗教學任務。
(2)學生學習使用Python 的熱情高、自主性強。在熟悉Python 環境下的圖像處理工具后,很多學生開始學習網上的一些開源的圖像處理項目,它們往往是用Python 編寫的。部分學生還接觸到了Tensorflow、Keras 等深度學習算法開發工具,開闊了眼界,也提高了能力。
(3)一個額外的收獲是,選用Python 做實驗語言有利于學生就業。在學習和使用Python 處理圖像的過程中,學生得到了更多的鍛煉。從學生畢業實習的情況看,使用Python 處理圖像的學生更受企業歡迎,符合企業的需求,能更順利地找到理想的工作。
總之,Python 免費開源,語法簡單,有眾多的擴展庫可以實現圖像處理的各種算法,是圖像處理編程的理想語言。在數字圖像處理教學中,Python 值得推廣,經合理地安排實驗內容,能獲得良好的教學效果。