用Python做影像處理
最近在做一件比較 evil 的事情——驗證碼識別,以此來學習一些新的技能。因為我是初學,對影像處理方面就不太瞭解了,欲要利吾事,必先利吾器,既然只是做一下實驗,那用 Python 來作原型開發再好不過了。在 Python 中,比較常用的影像處理庫是 PIL(Python Image Library),目前的版本是 1.1.6 ,用起來非常方便。大家可以在 http://www.pythonware.com/products/pil/index.htm 下載和學習。 在這裡,我主要是介紹一下做Image Recognition時可能會用到的一些 PIL 提供的功能,比像增強、還有濾波之類的。最後給出使用 Python 做影像處理與識別的優勢與劣勢。
基本影像處理 使用 PIL 之前需要 import Image 模組:import Image 然後你就可以使用Image.open(‘xx.bmp’) 來開啟一個位元影像檔案進行處理了。開啟檔案你不用擔心格式,也不用瞭解格式,無論什麼格式,都只要把檔案名稱丟給 Image.open 就可以了。真所謂 bmp、jpg、png、gif……,一個都不能少。img = Image.open(‘origin.png’) # 得到一個映像的執行個體對象 img圖 1原圖 影像處理中,最基本的就是色彩空間的轉換。一般而言,我們的映像都是 RGB 色彩空間的,但在Image Recognition當中,我們可能需要轉換映像到灰階圖、二值圖等不同的色彩空間。 PIL 在這方面也提供了極完備的支援,我們可以:new_img = img.convert(‘L’)把 img 轉換為 256 級灰階映像, convert() 是映像執行個體對象的一個方法,接受一個 mode 參數,用以指定一種色彩模式,mode 的取值可以是如下幾種:· 1 (1-bit pixels, black and white, stored with one pixel per byte)· L (8-bit pixels, black and white)· P (8-bit pixels, mapped to any other mode using a colour palette)· RGB (3x8-bit pixels, true colour)· RGBA (4x8-bit pixels, true colour with transparency mask)· CMYK (4x8-bit pixels, colour separation)· YCbCr (3x8-bit pixels, colour video format)· I (32-bit signed integer pixels)· F (32-bit floating point pixels)怎麼樣,夠豐富吧?其實如此之處,PIL 還有限制地支援以下幾種比較少見的色彩模式:LA (L with alpha), RGBX (true colour with padding) and RGBa (true colour with premultiplied alpha)。下面看一下 mode 為 ‘1’、’L’、’P’時轉換出來的映像:圖 2 mode = '1'圖 3 mode = 'L'圖 4 mode = 'P'convert() 函數也接受另一個隱含參數 matrix,轉換矩陣 matrix 是一個長度為4 或者16 tuple。下例是一個轉換 RGB 空間到 CIE XYZ 空間的例子: rgb2xyz = ( 0.412453, 0.357580, 0.180423, 0, 0.212671, 0.715160, 0.072169, 0, 0.019334, 0.119193, 0.950227, 0 ) out = im.convert("RGB", rgb2xyz) 除了完備的色彩空間轉換能力外, PIL 還提供了resize()、rotate()等函數以獲得改變大小,旋轉圖片等幾何變換能力,在Image Recognition方面,映像執行個體提供了一個 histogram() 方法來計算長條圖,非常方便實用。
映像增強 映像增強通常用以Image Recognition之前的預先處理,適當的映像增強能夠使得識別過程達到事半功倍的效果。 PIL 在這方面提供了一個名為 ImageEnhance 的模組,提供了幾種常見的映像增強方案:import ImageEnhanceenhancer = ImageEnhance.Sharpness(image)for i in range(8): factor = i / 4.0 enhancer.enhance(factor).show("Sharpness %f" % factor)上面的代碼即是一個典型的使用 ImageEnhance 模組的例子。 Sharpness 是 ImageEnhance 模組的一個類,用以銳利化圖片。這一模組主要包含如下幾個類:Color、Brightness、Contrast和Sharpness。它們都有一個共同的介面 .enhance(factor) ,接受一個浮點參數 factor,標示增強比例。下面看看這四個類在不同的 factor 下的效果圖 5 使用Color 進行色彩增強,factor 取值 [0, 4],步進 0.5圖 6 用 Birghtness 增強亮度,factor取值[0,4],步進0.5圖 7用 Contrast 增強對比, factor 取值 [0,4],步進0.5圖 8用 Sharpness 銳利化映像,factor取值 [0,4],步進0.5
映像 Filter PIL 在 Filter 方面的支援是非常完備的,除常見的模糊、浮雕、輪廓、邊緣增強和平滑,還有中值濾波、ModeFilter等,簡直方便到可以做自己做一個Photoshop。這些 Filter 都放置在 ImageFilter 模組中,ImageFilter主要包括兩部分內容,一是內建的 Filter,如 BLUR、DETAIL等,另一部分是 Filter 函數,可以指定不同的參數獲得不同的效果。樣本如下:import ImageFilterim1 = im.filter(ImageFilter.BLUR)im2 = im.filter(ImageFilter.MinFilter(3))im3 = im.filter(ImageFilter.MinFilter()) # same as MinFilter(3)可以看到 ImageFilter 模組的使用非常簡單,每一個 Filter 都只需要一行代碼就可調用,開發效率非常高。 圖 9使用 BLUR圖 10使用 CONTOUR圖 11使用 DETAIL圖 12使用 EMBOSS圖 13使用 EDGE_ENHANCE圖 14使用 EDGE_ENHANCE_MORE圖 15使用 FIND_EDGES圖 16使用 SHARPEN圖 17使用 SMOOTH圖 18使用 SMOOTH_MORE 以上是幾種內建的 Filter 的,除此之外, ImageFilter 還提供了一些 Filter 函數,下面我們來看看這些可以通過參數改變行為的 Filter 的效果:圖 19使用 Kernel(),參數:size = (3, 3), kernel = (0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5)圖 20使用 MaxFilter,預設參數圖 21使用 MinFilter,預設參數圖 22使用 MedianFilter,預設參數圖 23使用 ModeFilter,參數 size = 3圖 24使用 RankFilter,參數 size = 3, rank = 3
小結 到此,對 PIL 的介紹就告一段落了。總的來說,對於影像處理和識別,PIL 內建了強大的支援,從各種增強演算法到 Filter ,都讓人無法懷疑使用 Python 的可行性。 Python唯一的劣勢在於執行時間過慢,特別是當實現一些計算量大的演算法時候,需要極強的耐心。我曾用 Hough Transform(霍夫變換)來尋找映像中的直線,純 Python 的實現處理一個 340 * 100 的圖片也要花去數秒時間(P4 3.0G + 1G memory)。但使用 PIL 無需關注映像格式、內建的映像增強演算法和 Filter 演算法,這些優點使 Python 適合用於構造原型和進行實驗,在這兩方面Python 比 matlab 更加方便。商業的Image Recognition產品開發,可以考慮已經被 boost accepted的來自 adobe 的開源 C++ 庫 gil,可以兼顧執行效能和開發效率。