圖像識別的前期工作——使用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或神經網絡等方法進行學習,從而使計算機識別出正確的數字。后續文章將會介紹如何設別。

 


   出處:微信公眾號 "我是8位的"

   本文以學習、研究和分享為主,如需轉載,請聯系本人,標明作者和出處,非商業用途! 

   掃描二維碼關注作者公眾號“我是8位的”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM