最近在研究深度學習視覺相關的東西,常常須要寫python代碼搭建深度學習模型。好比寫CNN模型相關代碼時,咱們須要藉助python圖像庫來讀取圖像並進行一系列的圖像處理工做。我最經常使用的圖像庫固然是opencv,很強大很好用,可是opencv也有一些坑,不注意的話也會搞出大麻煩。近期我也在看一些別人寫的代碼,由於我的習慣不同,他們在作深度學習時用於圖片讀取的圖像庫各不相同,從opencv到PIL再到skimage等等各類庫都有,有些庫讀進來的圖片存儲方式也不太同樣,若是很差好總結這些主流圖像讀寫庫特色的話,之後看代碼寫代碼都會遇坑無數。這篇文章就總結了如下主流Python圖像庫的一些基本使用方法和須要注意的地方:python
opencv做爲我最經常使用的圖像處理庫,固然第一個介紹,而且介紹得比較全面。毋庸置疑,opencv是今天介紹得全部圖像庫中最全面也最強大的庫,若是咱們只想掌握一個圖像庫,我以爲opencv庫確定是最適合不過了。app
import cv2 import numpy as np #讀入圖片:默認彩色圖,cv2.IMREAD_GRAYSCALE灰度圖,cv2.IMREAD_UNCHANGED包含alpha通道 img = cv2.imread('1.jpg') cv2.imshow('src',img) print(img.shape) # (h,w,c) print(img.size) # 像素總數目 print(img.dtype) print(img) cv2.waitKey()
值得注意的是,opencv讀進來的圖片已是一個numpy矩陣了,彩色圖片維度是(高度,寬度,通道數)。數據類型是uint8。oop
#gray = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE) #灰度圖 #cv2.imshow('gray',gray) #也能夠這麼寫,先讀入彩色圖,再轉灰度圖 src = cv2.imread('1.jpg') gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) cv2.imshow('gray',gray) print(gray.shape) print(gray.size) print(gray) cv2.waitKey()
上面提到了兩種獲取灰度圖的方式,讀進來的灰度圖的矩陣格式是(高度,寬度)。性能
#注意,計算圖片路徑是錯的,Opencv也不會提醒你,但print img時獲得的結果是None img2 = cv2.imread('2.jpg') print(img2)
#如何解決「讀到的圖片不存在的問題」? #加入判斷語句,若是爲空,作異常處理 img2 = cv2.imread('2.jpg') if img2 == None: print('fail to load image!')
opencv讀入圖片的矩陣格式是:(height,width,channels)。而在深度學習中,由於要對不一樣通道應用卷積,因此會採起另外一種方式:(channels,height,width)。爲了應對該要求,咱們能夠這麼作學習
#注意到,opencv讀入的圖片的彩色圖是一個channel last的三維矩陣(h,w,c),即(高度,寬度,通道) #有時候在深度學習中用到的的圖片矩陣形式多是channel first,那咱們能夠這樣轉一下 print(img.shape) img = img.transpose(2,0,1) print(img.shape)
在深度學習搭建CNN時,每每要作相應的圖像數據處理,好比圖像要擴展維度,好比擴展成(batch_size,channels,height,width)。測試
對於這種要求,咱們能夠這麼作。ui
#有時候還要擴展維度,好比有時候咱們須要預測單張圖片,要在要加一列作圖片的個數,能夠這麼作 img = np.expand_dims(img, axis=0) print(img.shape)
上面提到的是預測階段時預測單張圖片的擴展維度的操做,若是是訓練階段,構建batch,即獲得這種形式:(batch_size,channels,height,width)。我通常喜歡這麼作3d
data_list = [] loop: im = cv2.imread('xxx.png') data_list.append(im) data_arr = np.array(data_list)
這樣子就能構形成咱們想要的形式了。code
#由於opencv讀入的圖片矩陣數值是0到255,有時咱們須要對其進行歸一化爲0~1 img3 = cv2.imread('1.jpg') img3 = img3.astype("float") / 255.0 #注意須要先轉化數據類型爲float print(img3.dtype) print(img3)
#存儲圖片 cv2.imwrite('test1.jpg',img3) #獲得的是全黑的圖片,由於咱們把它歸一化了 #因此要獲得可視化的圖,須要先*255還原 img3 = img3 * 255 cv2.imwrite('test2.jpg',img3) #這樣就能夠看到彩色原圖了
opencv對於讀進來的圖片的通道排列是BGR,而不是主流的RGB!謹記!orm
#opencv讀入的矩陣是BGR,若是想轉爲RGB,能夠這麼轉 img4 = cv2.imread('1.jpg') img4 = cv2.cvtColor(img4,cv2.COLOR_BGR2RGB)
#訪問像素 print(img4[10,10]) #3channels print(gray[10,10]) #1channel img4[10,10] = [255,255,255] gray[10,10] = 255 print(img4[10,10]) #3channels print(gray[10,10]) #1channel
#roi操做 roi = img4[200:550,100:450,:] cv2.imshow('roi',roi) cv2.waitKey()
#分離通道 img5 = cv2.imread('1.jpg') b,g,r = cv2.split(img5) #合併通道 img5 = cv2.merge((b,g,r)) #也能夠不拆分 img5[:,:,2] = 0 #將紅色通道值所有設0
from PIL import Image import numpy as np
PIL即Python Imaging Library,也即爲咱們所稱的Pillow,是一個很流行的圖像庫,它比opencv更爲輕巧,正因如此,它深受大衆的喜好。
PIL讀進來的圖像是一個對象,而不是咱們所熟知的numpy 矩陣。
img = Image.open('1.jpg') print(img.format) print(img.size) #注意,省略了通道 (w,h) print(img.mode) #L爲灰度圖,RGB爲真彩色,RGBA爲加了透明通道 img.show() # 顯示圖片
灰度圖的獲取
gray = Image.open('1.jpg').convert('L') gray.show()
#讀取不到圖片會拋出異常IOError,咱們能夠捕捉它,作異常處理 try: img2 = Image.open('2.jpg') except IOError: print('fail to load image!')
#pillow讀進來的圖片不是矩陣,咱們將圖片轉矩陣,channel last arr = np.array(img3) print(arr.shape) print(arr.dtype) print(arr)
灰度圖的轉化與彩圖轉化同樣
arr_gray = np.array(gray) print(arr_gray.shape) print(arr_gray.dtype) print(arr_gray)
#矩陣再轉爲圖像 new_im = Image.fromarray(arr) new_im.save('3.png')
#分離合並通道 r, g, b = img.split() img = Image.merge("RGB", (b, g, r))
img = img.copy() #複製圖像
img3 = Image.open('1.jpg') roi = img3.crop((0,0,300,300)) #(左上x,左上y,右下x,右下y)座標 roi.show()
matplotlib是一個科學繪圖神器,用的人很是多。
import matplotlib.pyplot as plt import numpy as np
image = plt.imread('1.jpg') plt.imshow(image) plt.show()
#也能夠關閉顯示x,y軸上的數字 image = plt.imread('1.jpg') plt.imshow(image) plt.axis('off') plt.show()
#plt.imread讀入的就是一個矩陣,跟opencv同樣,但彩圖讀進的是RGB,與opencv有區別 print(image.shape) # (h,w,c) print(image.size) print(image.dtype) print(image)
im_r = image[:,:,0] #紅色通道 plt.imshow(im_r) plt.show() #此時會發現顯示的是熱量圖,不是咱們預想的灰度圖,能夠添加 cmap 參數解決 plt.imshow(im_r,cmap='Greys_r') plt.show()
#與opencv結合使用 import cv2 im2 = cv2.imread('1.jpg') plt.imshow(im2) plt.axis('off') plt.show() #發現圖像顏色怪怪的,緣由固然是咱們前面提到的RGB順序不一樣的緣由啦,轉一下就好 im2 = cv2.cvtColor(im2,cv2.COLOR_BGR2RGB) plt.imshow(im2) plt.axis('off') plt.show() #因此不管用什麼庫讀進圖片,只要把圖片改成矩陣,那麼matplotlib就能夠處理了
#再試一試pillow和matplotlib結合 from PIL import Image im3 = Image.open('1.jpg') im3 = np.array(im3) plt.figure(1) plt.imshow(im3) plt.axis('off') #存儲圖像,注意,必須在show以前savefig,不然存儲的圖片一片空白 plt.savefig('timo.jpg') plt.show()
#最後以一個綜合例子總結matplotlib最基本的圖片顯示技巧吧 im_lol1 = plt.imread('lol.jpg') im_lol2 = plt.imread('1.jpg') figure = plt.figure(figsize=(20,10)) # 調整顯示圖片的大小 ''' figsize參數:指定繪圖對象的寬度和高度,單位爲英寸;dpi參數指定繪圖對象的分辨率, 即每英寸多少個像素,缺省值爲80。所以本例中所建立的圖表窗口的寬度爲8*80 = 640像素 ''' plt.axis("off")#不顯示刻度 ax = figure.add_subplot(121) # 圖片以1行2列的形式顯示 plt.axis('off') ax.imshow(im_lol1) #第一張圖 ax.set_title('lol image 1')#給圖片加titile ax = figure.add_subplot(122) plt.axis('off') ax.imshow(im_lol2) ax.set_title('lol image 2')#給圖片加titile plt.savefig('twp.jpg') plt.show()
from scipy import misc import matplotlib.pyplot as plt
im = misc.imread('1.jpg') print(im.dtype) print(im.size) print(im.shape) misc.imsave('misc1.png',im) plt.imshow(im) plt.show() print(im)
能夠看到,有warining,提示咱們imread和imsave在後來的版本將會被棄用,叫咱們使用imageio.imread和imageio.imwrite。
咱們根據她的提示,使用imageio模塊進行圖片讀寫,warning也就沒有了。
import imageio im2 = imageio.imread('1.jpg') print(im2.dtype) print(im2.size) print(im2.shape) plt.imshow(im) plt.show() print(im2) imageio.imsave('imageio.png',im2)
from skimage import io im = io.imread('1.jpg') print(im.shape) # numpy矩陣,(h,w,c) print(im.dtype) print(im.size) io.imshow(im) io.imsave('sk.png',im) print(im)
圖像也是以numpy array形式讀入。
灰度圖的獲取方式:
im2 = io.imread('1.jpg',as_grey=True) #讀入灰度圖 print(im2.dtype) print(im2.size) print(im2.shape) io.imshow(im2) io.imsave('sk_gray.png',im2) io.show() print(im2)
能夠看到,灰度圖像的矩陣的值被歸一化了,注意注意!
也能夠以這種方式得到灰度圖:
from skimage import color im3 = io.imread('1.jpg') im3 = color.rgb2grey(im3) print(im3.dtype) print(im3.size) print(im3.shape) io.imshow(im3) io.show() ''' skimage.color.rgb2grey(rgb) skimage.color.rgb2hsv(rgb) skimage.color.rgb2lab(rgb) skimage.color.gray2rgb(image) skimage.color.hsv2rgb(hsv) skimage.color.lab2rgb(lab) '''