Python各類(lèi)圖像庫(kù)的圖片讀寫(xiě)方式總結(jié)(推薦)
最近在研究深度學(xué)習(xí)視覺(jué)相關(guān)的東西,經(jīng)常需要寫(xiě)python代碼搭建深度學(xué)習(xí)模型。比如寫(xiě)CNN模型相關(guān)代碼時(shí),我們需要借助python圖像庫(kù)來(lái)讀取圖像并進(jìn)行一系列的圖像處理工作。我最常用的圖像庫(kù)當(dāng)然是opencv,很強(qiáng)大很好用,但是opencv也有一些坑,不注意的話(huà)也會(huì)搞出大麻煩。近期我也在看一些別人寫(xiě)的代碼,因?yàn)閭€(gè)人習(xí)慣不一樣,他們?cè)谧錾疃葘W(xué)習(xí)時(shí)用于圖片讀取的圖像庫(kù)各不相同,從opencv到PIL再到skimage等等各種庫(kù)都有,有些庫(kù)讀進(jìn)來(lái)的圖片存儲(chǔ)方式也不太一樣,如果不好好總結(jié)這些主流圖像讀寫(xiě)庫(kù)特點(diǎn)的話(huà),以后看代碼寫(xiě)代碼都會(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ù)類(lèi)型是uint8。
#gray = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE) #灰度圖
#cv2.imshow('gray',gray)
#也可以這么寫(xiě),先讀入彩色圖,再轉(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ù)類(lèi)型為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,也即為我們所稱(chēng)的Pillow,是一個(gè)很流行的圖像庫(kù),它比opencv更為輕巧,正因如此,它深受大眾的喜愛(ài)。
圖像讀寫(xiě)
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)行圖片讀寫(xiě),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é)
- 除了opencv讀入的彩色圖片以BGR順序存儲(chǔ)外,其他所有圖像庫(kù)讀入彩色圖片都以RGB存儲(chǔ)。
- 除了PIL讀入的圖片是img類(lèi)之外,其他庫(kù)讀進(jìn)來(lái)的圖片都是以numpy 矩陣。
- 各大圖像庫(kù)的性能,老大哥當(dāng)屬opencv,無(wú)論是速度還是圖片操作的全面性,都屬于碾壓的存在,畢竟他是一個(gè)巨大的cv專(zhuān)用庫(kù)。下面那張圖就是我從知乎盜來(lái)的一張關(guān)于各個(gè)主流圖像庫(kù)的一些性能比較圖,從測(cè)試結(jié)果看來(lái),opencv確實(shí)勝出太多了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Python空間數(shù)據(jù)處理之GDAL讀寫(xiě)遙感圖像
- python 對(duì)一幅灰度圖像進(jìn)行直方圖均衡化
- 詳解基于python的圖像Gabor變換及特征提取
- Python+OpenCV圖像處理——圖像二值化的實(shí)現(xiàn)
- Python+OpenCV圖像處理——實(shí)現(xiàn)輪廓發(fā)現(xiàn)
- Python+OpenCV圖像處理——實(shí)現(xiàn)直線(xiàn)檢測(cè)
- Python+OpenCV圖像處理—— 色彩空間轉(zhuǎn)換
- 如何使用Python調(diào)整圖像大小
- Python Opencv圖像處理基本操作代碼詳解
- Python圖像處理二值化方法實(shí)例匯總
- Python圖像讀寫(xiě)方法對(duì)比
相關(guān)文章
VSCode2022配置Python3.9.6的詳細(xì)教程
這篇文章主要介紹了VSCode2022配置Python3.9.6教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
Python實(shí)現(xiàn)圖像手繪效果的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Python語(yǔ)言實(shí)現(xiàn)圖像手繪效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2022-09-09
Python利用subplots_adjust方法解決圖表與畫(huà)布的間距問(wèn)題
這篇文章主要介紹了如何在使用python?的?matplotlib庫(kù)繪圖時(shí),?使用subplots_adjust()方法來(lái)調(diào)整圖表與畫(huà)布之間的間距,以及圖表與圖表之間的間距,感興趣的可以了解一下2022-04-04
django haystack實(shí)現(xiàn)全文檢索的示例代碼
這篇文章主要介紹了django haystack實(shí)現(xiàn)全文檢索的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
pycharm訪問(wèn)mysql數(shù)據(jù)庫(kù)的方法步驟
這篇文章主要介紹了pycharm訪問(wèn)mysql數(shù)據(jù)庫(kù)的方法步驟。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
python腳本爬取字體文件的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了利用python腳本爬取字體文件的實(shí)現(xiàn)方法,文中分享了爬取兩個(gè)不同網(wǎng)站的示例代碼,相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-04-04
python中使用mysql數(shù)據(jù)庫(kù)詳細(xì)介紹
這篇文章主要介紹了python中使用mysql數(shù)據(jù)庫(kù)詳細(xì)介紹,本文起講解了安裝mysql、安裝MySQL-python、mysql 的基本操作、python 操作mysql數(shù)據(jù)庫(kù)基礎(chǔ)等內(nèi)容,需要的朋友可以參考下2015-03-03
Python3+Appium安裝及Appium模擬微信登錄方法詳解
這篇文章主要介紹了Python3+Appium安裝及使用方法詳解,需要的朋友可以參考下2021-02-02
Python利用matplotlib.pyplot.boxplot()繪制箱型圖實(shí)例代碼
相信大家應(yīng)該都知道Python繪制箱線(xiàn)圖主要用matplotlib庫(kù)里pyplot模塊里的boxplot()函數(shù),下面這篇文章主要給大家介紹了關(guān)于Python利用matplotlib.pyplot.boxplot()繪制箱型圖的相關(guān)資料,需要的朋友可以參考下2022-08-08

