Python各類圖像庫的圖片讀寫方式總結(jié)(推薦)
最近在研究深度學(xué)習(xí)視覺相關(guān)的東西,經(jīng)常需要寫python代碼搭建深度學(xué)習(xí)模型。比如寫CNN模型相關(guān)代碼時,我們需要借助python圖像庫來讀取圖像并進(jìn)行一系列的圖像處理工作。我最常用的圖像庫當(dāng)然是opencv,很強(qiáng)大很好用,但是opencv也有一些坑,不注意的話也會搞出大麻煩。近期我也在看一些別人寫的代碼,因為個人習(xí)慣不一樣,他們在做深度學(xué)習(xí)時用于圖片讀取的圖像庫各不相同,從opencv到PIL再到skimage等等各種庫都有,有些庫讀進(jìn)來的圖片存儲方式也不太一樣,如果不好好總結(jié)這些主流圖像讀寫庫特點的話,以后看代碼寫代碼都會遇坑無數(shù)。這篇文章就總結(jié)了以下主流Python圖像庫的一些基本使用方法和需要注意的地方:
1.opencv
2.PIL(pillow)
3.matplotlib.image
4.scipy.misc
5.skimage
opencv: cv2.imread
opencv作為我最常用的圖像處理庫,當(dāng)然第一個介紹,并且介紹得比較全面。毋庸置疑,opencv是今天介紹得所有圖像庫中最全面也最強(qiáng)大的庫,如果我們只想掌握一個圖像庫,我覺得opencv庫肯定是最適合不過了。
圖片讀取操作
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)來的圖片已經(jīng)是一個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)來的灰度圖的矩陣格式是(高度,寬度)。
#注意,計算圖片路徑是錯的,Opencv也不會提醒你,但print img時得到的結(jié)果是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)。而在深度學(xué)習(xí)中,因為要對不同通道應(yīng)用卷積,所以會采取另一種方式:(channels,height,width)。為了應(yīng)對該要求,我們可以這么做
#注意到,opencv讀入的圖片的彩色圖是一個channel last的三維矩陣(h,w,c),即(高度,寬度,通道) #有時候在深度學(xué)習(xí)中用到的的圖片矩陣形式可能是channel first,那我們可以這樣轉(zhuǎn)一下 print(img.shape) img = img.transpose(2,0,1) print(img.shape)

在深度學(xué)習(xí)搭建CNN時,往往要做相應(yīng)的圖像數(shù)據(jù)處理,比如圖像要擴(kuò)展維度,比如擴(kuò)展成(batch_size,channels,height,width)。
對于這種要求,我們可以這么做。
#有時候還要擴(kuò)展維度,比如有時候我們需要預(yù)測單張圖片,要在要加一列做圖片的個數(shù),可以這么做 img = np.expand_dims(img, axis=0) print(img.shape)

上面提到的是預(yù)測階段時預(yù)測單張圖片的擴(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)造成我們想要的形式了。
圖片歸一化
#因為opencv讀入的圖片矩陣數(shù)值是0到255,有時我們需要對其進(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)

存儲圖片
#存儲圖片
cv2.imwrite('test1.jpg',img3) #得到的是全黑的圖片,因為我們把它歸一化了
#所以要得到可視化的圖,需要先*255還原
img3 = img3 * 255
cv2.imwrite('test2.jpg',img3) #這樣就可以看到彩色原圖了
opencv大坑之BGR
opencv對于讀進(jìn)來的圖片的通道排列是BGR,而不是主流的RGB!謹(jǐn)記!
#opencv讀入的矩陣是BGR,如果想轉(zhuǎn)為RGB,可以這么轉(zhuǎn)
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操作
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,是一個很流行的圖像庫,它比opencv更為輕巧,正因如此,它深受大眾的喜愛。
圖像讀寫
PIL讀進(jìn)來的圖像是一個對象,而不是我們所熟知的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讀進(jìn)來的圖片不是矩陣,我們將圖片轉(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)

存儲圖片
#矩陣再轉(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,左上y,右下x,右下y)坐標(biāo)
roi.show()
matplotlib:matplotlib.image.imread
matplotlib是一個科學(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讀入的就是一個矩陣,跟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() #此時會發(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()
#所以無論用什么庫讀進(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')
#存儲圖像,注意,必須在show之前savefig,否則存儲的圖片一片空白
plt.savefig('timo.jpg')
plt.show()

#最后以一個綜合例子總結(jié)matplotlib最基本的圖片顯示技巧吧
im_lol1 = plt.imread('lol.jpg')
im_lol2 = plt.imread('1.jpg')
figure = plt.figure(figsize=(20,10)) # 調(diào)整顯示圖片的大小
'''
figsize參數(shù):指定繪圖對象的寬度和高度,單位為英寸;dpi參數(shù)指定繪圖對象的分辨率,
即每英寸多少個像素,缺省值為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在后來的版本將會被棄用,叫我們使用imageio.imread和imageio.imwrite。
我們根據(jù)她的提示,使用imageio模塊進(jìn)行圖片讀寫,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)

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順序存儲外,其他所有圖像庫讀入彩色圖片都以RGB存儲。
- 除了PIL讀入的圖片是img類之外,其他庫讀進(jìn)來的圖片都是以numpy 矩陣。
- 各大圖像庫的性能,老大哥當(dāng)屬opencv,無論是速度還是圖片操作的全面性,都屬于碾壓的存在,畢竟他是一個巨大的cv專用庫。下面那張圖就是我從知乎盜來的一張關(guān)于各個主流圖像庫的一些性能比較圖,從測試結(jié)果看來,opencv確實勝出太多了。

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

