本文主要介紹使用pillow對圖像進行簡單處理,進而引出圖像處理與手寫識別的關係。 ...
pillow是個很好用的python圖像處理庫,可以到官方網站下載最新的文件。如果官網的任何PIL版本都不能與自己的python版本對應,或安裝成功後發現運行出錯,可以嘗試從一個非官方的whl網站下載:http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy 這個網站的內容相當豐富,而且版本齊全。
打開圖片
from PIL import Image import matplotlib.pyplot as plt img = Image.open('girl.png') img.show()
控制台顯示:size=(461, 603), mode=RGBA, format=PNG
代碼很簡單,但PIL使用操作系統的預設方式打開圖片,我們需要用一些更牛叉的方式打開:
1 from PIL import Image 2 import matplotlib.pyplot as plt 3 4 img = Image.open('girl0.png') 5 model = img.convert('L') 6 plt.figure("girl") 7 #the argument comp is Colormap 8 plt.imshow(model, cmap='pink') 9 plt.show()
其中img.convert指定一種色彩模式:
- 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)
分離rgba
rgb指紅綠藍光色三原色,a指alpha通道,一般用作不透明度參數
img = Image.open('girl0.png') # 分離rgba r, g, b, a = img.split() plt.figure("girl0") plt.imshow(r) plt.show()
需要註意的是,並非所有圖片都有alpha通道,此時 img.split()僅能返回r,g,b
顯示多個圖片
from PIL import Image import matplotlib.pyplot as plt img = Image.open('girl0.png') gray = img.convert('L') # 分離rgba r, g, b, a = img.split() plt.figure("girl") def setPlot(num, title): #subplot(nrows, ncols, plot_number) #圖表的整個繪圖區域被等分為numRows行和numCols列,然後按照從左到右、從上到下的順序對每個區域進行編號,左上區域的編號為1 plt.subplot(2, 3, num) plt.title(title) plt.axis('off') setPlot(1, 'origin') plt.imshow(img) setPlot(2, 'gray') plt.imshow(gray, cmap='gray') setPlot(3, 'rgba') # 合併rgba plt.imshow(Image.merge('RGBA', (r, g, b, a))) setPlot(4, 'r') plt.imshow(r) setPlot(5, 'g') plt.imshow(g) setPlot(6, 'b') plt.imshow(b)
二值化處理
到了關鍵時刻
from PIL import Image import matplotlib.pyplot as plt #二值化處理 img = Image.open('girl0.png') gray = img.convert('L') WHITE, BLACK = 1, 0 img_new = gray.point(lambda x: WHITE if x > 128 else BLACK) plt.imshow(img_new, cmap='gray') plt.show()
圖片由像素組成,每個像素對應著rgb值,整個圖片可以看成一個矩陣。我們將大於128的像素點轉換為1,其它轉換為0。如果有一張背景色是彩色的手寫文字,經過二值化處理後得到這樣的圖片:
圖片壓縮
如果圖片大小不一,不利於下一步工作,在此需要將圖片壓縮成統一大小,對於手寫數字,可將其壓縮為32*32
1 #等比例壓縮圖片 2 #參考 http://fc-lamp.blog.163.com/blog/static/174566687201282424018946/ 3 def resizeImg(**args): 4 #dst_w,dst_h 目標圖片大小, save_q 圖片質量 5 args_key = {'ori_img':'', 'dst_img':'', 'dst_w':'', 'dst_h':'', 'save_q':75} 6 arg = {} 7 for key in args_key: 8 if key in args: 9 arg[key] = args[key] 10 11 im = Image.open(arg['ori_img']) 12 ori_w, ori_h = im.size 13 widthRatio = heightRatio = None 14 ratio = 1 15 if (ori_w and ori_w > arg['dst_w']) or (ori_h and ori_h > arg['dst_h']): 16 if arg['dst_w'] and ori_w > arg['dst_w']: 17 widthRatio = float(arg['dst_w']) / ori_w 18 if arg['dst_h'] and ori_h > arg['dst_h']: 19 heightRatio = float(arg['dst_h']) / ori_h 20 21 if widthRatio and heightRatio: 22 if widthRatio < heightRatio: 23 ratio = widthRatio 24 else: 25 ratio = heightRatio 26 27 if widthRatio and not heightRatio: 28 ratio = widthRatio 29 if heightRatio and not widthRatio: 30 ratio = heightRatio 31 32 newWidth = int(ori_w * ratio) 33 newHeight = int(ori_h * ratio) 34 else: 35 newWidth = ori_w 36 newHeight = ori_h 37 38 im.resize((newWidth, newHeight), Image.ANTIALIAS).save(arg['dst_img'], quality=arg['save_q'])
可以將二值化處理後的圖片列印出來
1 resizeImg(ori_img='7.jpg', dst_img='7_1.jpg', dst_w=32, dst_h=32, save_q=60) 2 3 #二值化處理 4 img = Image.open('7_1.jpg') 5 gray = img.convert('L') 6 7 WHITE, BLACK = 1, 0 8 img_new = gray.point(lambda x: WHITE if x > 128 else BLACK) 9 arr = nmp.array(img_new) 10 11 for i in range(arr.shape[0]): 12 print(arr[i].flatten())
於是手寫數字變成了這樣:
這就好玩了。其基本思路是將多維特征轉換為容易識別的二維特征,使用KNN或神經網路等方法進行學習,從而使電腦識別出正確的數字。後續文章將會介紹如何設別。
參考文獻:
http://fc-lamp.blog.163.com/blog/static/174566687201282424018946
作者:我是8位的
出處:http://www.cnblogs.com/bigmonkey
本文以學習、研究和分享為主,如需轉載,請聯繫本人,標明作者和出處,非商業用途!