您好,登錄后才能下訂單哦!
最近在研究深度學(xué)習(xí)視覺(jué)相關(guān)的東西,經(jīng)常需要寫python代碼搭建深度學(xué)習(xí)模型。比如寫CNN模型相關(guān)代碼時(shí),我們需要借助python圖像庫(kù)來(lái)讀取圖像并進(jìn)行一系列的圖像處理工作。我最常用的圖像庫(kù)當(dāng)然是opencv,很強(qiáng)大很好用,但是opencv也有一些坑,不注意的話也會(huì)搞出大麻煩。近期我也在看一些別人寫的代碼,因?yàn)閭€(gè)人習(xí)慣不一樣,他們?cè)谧錾疃葘W(xué)習(xí)時(shí)用于圖片讀取的圖像庫(kù)各不相同,從opencv到PIL再到skimage等等各種庫(kù)都有,有些庫(kù)讀進(jìn)來(lái)的圖片存儲(chǔ)方式也不太一樣,如果不好好總結(jié)這些主流圖像讀寫庫(kù)特點(diǎn)的話,以后看代碼寫代碼都會(huì)遇坑無(wú)數(shù)。這篇文章就總結(jié)了以下主流Python圖像庫(kù)的一些基本使用方法和需要注意的地方:
1.opencv
2.PIL(pillow)
3.matplotlib.image
4.scipy.misc
5.skimage
opencv: cv2.imread
opencv作為我最常用的圖像處理庫(kù),當(dāng)然第一個(gè)介紹,并且介紹得比較全面。毋庸置疑,opencv是今天介紹得所有圖像庫(kù)中最全面也最強(qiáng)大的庫(kù),如果我們只想掌握一個(gè)圖像庫(kù),我覺(jué)得opencv庫(kù)肯定是最適合不過(guò)了。
圖片讀取操作
import cv2 import numpy as np #讀入圖片:默認(rèn)彩色圖,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) # 像素總數(shù)目 print(img.dtype) print(img) cv2.waitKey()
值得注意的是,opencv讀進(jìn)來(lái)的圖片已經(jīng)是一個(gè)numpy矩陣了,彩色圖片維度是(高度,寬度,通道數(shù))。數(shù)據(jù)類型是uint8。
#gray = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE) #灰度圖 #cv2.imshow('gray',gray) #也可以這么寫,先讀入彩色圖,再轉(zhuǎn)灰度圖 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()
上面提到了兩種獲取灰度圖的方式,讀進(jìn)來(lái)的灰度圖的矩陣格式是(高度,寬度)。
#注意,計(jì)算圖片路徑是錯(cuò)的,Opencv也不會(huì)提醒你,但print img時(shí)得到的結(jié)果是None img2 = cv2.imread('2.jpg') print(img2)
#如何解決“讀到的圖片不存在的問(wèn)題”? #加入判斷語(yǔ)句,如果為空,做異常處理 img2 = cv2.imread('2.jpg') if img2 == None: print('fail to load image!')
圖片矩陣變換
opencv讀入圖片的矩陣格式是:(height,width,channels)。而在深度學(xué)習(xí)中,因?yàn)橐獙?duì)不同通道應(yīng)用卷積,所以會(huì)采取另一種方式:(channels,height,width)。為了應(yīng)對(duì)該要求,我們可以這么做
#注意到,opencv讀入的圖片的彩色圖是一個(gè)channel last的三維矩陣(h,w,c),即(高度,寬度,通道) #有時(shí)候在深度學(xué)習(xí)中用到的的圖片矩陣形式可能是channel first,那我們可以這樣轉(zhuǎn)一下 print(img.shape) img = img.transpose(2,0,1) print(img.shape)
在深度學(xué)習(xí)搭建CNN時(shí),往往要做相應(yīng)的圖像數(shù)據(jù)處理,比如圖像要擴(kuò)展維度,比如擴(kuò)展成(batch_size,channels,height,width)。
對(duì)于這種要求,我們可以這么做。
#有時(shí)候還要擴(kuò)展維度,比如有時(shí)候我們需要預(yù)測(cè)單張圖片,要在要加一列做圖片的個(gè)數(shù),可以這么做 img = np.expand_dims(img, axis=0) print(img.shape)
上面提到的是預(yù)測(cè)階段時(shí)預(yù)測(cè)單張圖片的擴(kuò)展維度的操作,如果是訓(xùn)練階段,構(gòu)建batch,即得到這種形式:(batch_size,channels,height,width)。我一般喜歡這么做
data_list = [] loop: im = cv2.imread('xxx.png') data_list.append(im) data_arr = np.array(data_list)
這樣子就能構(gòu)造成我們想要的形式了。
圖片歸一化
#因?yàn)閛pencv讀入的圖片矩陣數(shù)值是0到255,有時(shí)我們需要對(duì)其進(jìn)行歸一化為0~1 img3 = cv2.imread('1.jpg') img3 = img3.astype("float") / 255.0 #注意需要先轉(zhuǎn)化數(shù)據(jù)類型為float print(img3.dtype) print(img3)
存儲(chǔ)圖片
#存儲(chǔ)圖片 cv2.imwrite('test1.jpg',img3) #得到的是全黑的圖片,因?yàn)槲覀儼阉鼩w一化了 #所以要得到可視化的圖,需要先*255還原 img3 = img3 * 255 cv2.imwrite('test2.jpg',img3) #這樣就可以看到彩色原圖了
opencv大坑之BGR
opencv對(duì)于讀進(jìn)來(lái)的圖片的通道排列是BGR,而不是主流的RGB!謹(jǐn)記!
#opencv讀入的矩陣是BGR,如果想轉(zhuǎn)為RGB,可以這么轉(zhuǎn) img4 = cv2.imread('1.jpg') img4 = cv2.cvtColor(img4,cv2.COLOR_BGR2RGB)
訪問(wèn)像素
#訪問(wèn)像素 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操作 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 #將紅色通道值全部設(shè)0
PIL:PIL.Image.open
圖片讀取
from PIL import Image import numpy as np
PIL即Python Imaging Library,也即為我們所稱的Pillow,是一個(gè)很流行的圖像庫(kù),它比opencv更為輕巧,正因如此,它深受大眾的喜愛(ài)。
圖像讀寫
PIL讀進(jìn)來(lái)的圖像是一個(gè)對(duì)象,而不是我們所熟知的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()
#讀取不到圖片會(huì)拋出異常IOError,我們可以捕捉它,做異常處理 try: img2 = Image.open('2.jpg') except IOError: print('fail to load image!')
#pillow讀進(jìn)來(lái)的圖片不是矩陣,我們將圖片轉(zhuǎn)矩陣,channel last arr = np.array(img3) print(arr.shape) print(arr.dtype) print(arr)
灰度圖的轉(zhuǎn)化與彩圖轉(zhuǎn)化一樣
arr_gray = np.array(gray) print(arr_gray.shape) print(arr_gray.dtype) print(arr_gray)
存儲(chǔ)圖片
#矩陣再轉(zhuǎn)為圖像 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() #復(fù)制圖像
ROI獲取
img3 = Image.open('1.jpg') roi = img3.crop((0,0,300,300)) #(左上x(chóng),左上y,右下x,右下y)坐標(biāo) roi.show()
matplotlib:matplotlib.image.imread
matplotlib是一個(gè)科學(xué)繪圖神器,用的人非常多。
import matplotlib.pyplot as plt import numpy as np
image = plt.imread('1.jpg') plt.imshow(image) plt.show()
#也可以關(guān)閉顯示x,y軸上的數(shù)字 image = plt.imread('1.jpg') plt.imshow(image) plt.axis('off') plt.show()
#plt.imread讀入的就是一個(gè)矩陣,跟opencv一樣,但彩圖讀進(jìn)的是RGB,與opencv有區(qū)別 print(image.shape) # (h,w,c) print(image.size) print(image.dtype) print(image)
im_r = image[:,:,0] #紅色通道 plt.imshow(im_r) plt.show() #此時(shí)會(huì)發(fā)現(xiàn)顯示的是熱量圖,不是我們預(yù)想的灰度圖,可以添加 cmap 參數(shù)解決 plt.imshow(im_r,cmap='Greys_r') plt.show()
#與opencv結(jié)合使用 import cv2 im2 = cv2.imread('1.jpg') plt.imshow(im2) plt.axis('off') plt.show() #發(fā)現(xiàn)圖像顏色怪怪的,原因當(dāng)然是我們前面提到的RGB順序不同的原因啦,轉(zhuǎn)一下就好 im2 = cv2.cvtColor(im2,cv2.COLOR_BGR2RGB) plt.imshow(im2) plt.axis('off') plt.show() #所以無(wú)論用什么庫(kù)讀進(jìn)圖片,只要把圖片改為矩陣,那么matplotlib就可以處理了
#再試一試pillow和matplotlib結(jié)合 from PIL import Image im3 = Image.open('1.jpg') im3 = np.array(im3) plt.figure(1) plt.imshow(im3) plt.axis('off') #存儲(chǔ)圖像,注意,必須在show之前savefig,否則存儲(chǔ)的圖片一片空白 plt.savefig('timo.jpg') plt.show()
#最后以一個(gè)綜合例子總結(jié)matplotlib最基本的圖片顯示技巧吧 im_lol1 = plt.imread('lol.jpg') im_lol2 = plt.imread('1.jpg') figure = plt.figure(figsize=(20,10)) # 調(diào)整顯示圖片的大小 ''' figsize參數(shù):指定繪圖對(duì)象的寬度和高度,單位為英寸;dpi參數(shù)指定繪圖對(duì)象的分辨率, 即每英寸多少個(gè)像素,缺省值為80。因此本例中所創(chuàng)建的圖表窗口的寬度為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 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在后來(lái)的版本將會(huì)被棄用,叫我們使用imageio.imread和imageio.imwrite。
我們根據(jù)她的提示,使用imageio模塊進(jìn)行圖片讀寫,warning也就沒(méi)有了。
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)
skimage:skimage.io.imread
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) '''
總結(jié)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。