最近在研究深度學習視覺相關的東西,經常需要寫python代碼搭建深度學習模型。比如寫CNN模型相關代碼時,我們需要借助python圖像庫來讀取圖像并進行一系列的圖像處理工作。我最常用的圖像庫當然是opencv,很強大很好用,但是opencv也有一些坑,不注意的話也會搞出大麻煩。近期我也在看一些別人寫的代碼,因為個人習慣不一樣,他們在做深度學習時用于圖片讀取的圖像庫各不相同,從opencv到PIL再到skimage等等各種庫都有,有些庫讀進來的圖片存儲方式也不太一樣,如果不好好總結這些主流圖像讀寫庫特點的話,以后看代碼寫代碼都會遇坑無數。這篇文章就總結了以下主流Python圖像庫的一些基本使用方法和需要注意的地方:
1.opencv
2.PIL(pillow)
3.matplotlib.image
4.scipy.misc
5.skimage
opencv: cv2.imread
opencv作為我最常用的圖像處理庫,當然第一個介紹,并且介紹得比較全面。毋庸置疑,opencv是今天介紹得所有圖像庫中最全面也最強大的庫,如果我們只想掌握一個圖像庫,我覺得opencv庫肯定是最適合不過了。
圖片讀取操作
import cv2import 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。
#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時得到的結果是Noneimg2 = 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)。
對于這種要求,我們可以這么做。
#有時候還要擴展維度,比如有時候我們需要預測單張圖片,要在要加一列做圖片的個數,可以這么做img = np.expand_dims(img, axis=0)print(img.shape)

上面提到的是預測階段時預測單張圖片的擴展維度的操作,如果是訓練階段,構建batch,即得到這種形式:(batch_size,channels,height,width)。我一般喜歡這么做
data_list = [] loop: im = cv2.imread('xxx.png') data_list.append(im)data_arr = np.array(data_list)這樣子就能構造成我們想要的形式了。
圖片歸一化
#因為opencv讀入的圖片矩陣數值是0到255,有時我們需要對其進行歸一化為0~1img3 = cv2.imread('1.jpg')img3 = img3.astype("float") / 255.0 #注意需要先轉化數據類型為floatprint(img3.dtype)print(img3) 
存儲圖片
#存儲圖片cv2.imwrite('test1.jpg',img3) #得到的是全黑的圖片,因為我們把它歸一化了#所以要得到可視化的圖,需要先*255還原img3 = img3 * 255cv2.imwrite('test2.jpg',img3) #這樣就可以看到彩色原圖了opencv大坑之BGR
opencv對于讀進來的圖片的通道排列是BGR,而不是主流的RGB!謹記!
#opencv讀入的矩陣是BGR,如果想轉為RGB,可以這么轉img4 = cv2.imread('1.jpg')img4 = cv2.cvtColor(img4,cv2.COLOR_BGR2RGB)訪問像素
#訪問像素print(img4[10,10]) #3channelsprint(gray[10,10]) #1channelimg4[10,10] = [255,255,255]gray[10,10] = 255print(img4[10,10]) #3channelsprint(gray[10,10]) #1channel

ROI操作
#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 #將紅色通道值全部設0PIL:PIL.Image.open
圖片讀取
from PIL import Imageimport 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 lastarr = 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() #復制圖像
ROI獲取
img3 = Image.open('1.jpg')roi = img3.crop((0,0,300,300)) #(左上x,左上y,右下x,右下y)坐標roi.show()matplotlib:matplotlib.image.imread
matplotlib是一個科學繪圖神器,用的人非常多。
import matplotlib.pyplot as pltimport 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 cv2im2 = 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 Imageim3 = 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() 
scipy.misc:scipy.misc.imread
from scipy import miscimport 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 imageioim2 = 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) 
skimage:skimage.io.imread
from skimage import ioim = 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 colorim3 = 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)''' 
總結

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答