python繪圖庫有很多,底層的就是matplotlib,另外還有基於matplotlib的更方便,代碼可讀性更強的庫,比如seaborn、plotnine等。各個庫之間的對比:
https://www.zhihu.com/question/39684179
matplotlib
在python下一般使用matplotlib包下的pyplot,所以通常import matplotlib.pyplot as plt方便使用它的繪圖函數。下面僅記錄matplotlib3.2.0之后的版本。
通用函數
plt.show()
顯示繪圖窗口。
plt.figure()
創建繪圖新窗口並傳給fig:
fig = plt.figure()
fig能使用下面繪圖、創建子圖等函數。不創建新窗口直接plt.function()也能繪圖,默認一個窗口。
fig.add_subplot()
給窗口添加子圖像,參數有三個,分別是子圖像的行、列、索引。兩種使用方式:
ax = fig.add_subplot(numbRow, numbCol, plotNum)
ax = fig.add_subplot(111)
前一種是一般的用逗號隔開,明確三個參數。后一種是三個整數參數直接合成一個整數傳入,這要求這個整數只能是3位的,這樣才能唯一確定用戶傳入的參數。(比如223,就是把圖像划分成2*2的格子,添加一個子圖像在第三個格子里)
fig.subplots()
同時創建窗口和多個子圖像的方法,用法如下:
import matplotlib.pyplot as plt fig, axs = plt.subplots(2,2) axs[0,0].plot([0,1],[0,1]) plt.show()
fig為創建的窗口對象,axs為多個子圖對象的二維數組,因此可以通過索引獲取子圖對象。
plt.imsave()
用於保存圖像,因為源代碼中沒有提示,很容易因為傳參順序而出錯。用法如下:
plt.imsave(name,img)#先傳名字再傳img數組
圖例
為圖像添加圖例,在畫圖函數中添加label屬性就行。如:
ax.plot(X,Y,label = '圖例')
然后使用legend()函數顯示所有的圖例,它可以設置圖例的位置等參數:
ax.legend(loc='best') #看這個介紹https://blog.csdn.net/qq_35240640/article/details/89478439
顯示中文(不然可能亂碼):
plt.rcParams['font.sans-serif']=['SimHei'] #用來正常顯示中文標簽 plt.rcParams['axes.unicode_minus']=False #用來正常顯示負號
圖像標題
ax.set_title('aaa',fontsize=12,color='r')
坐標軸設置
ax.set_xlim([-2, 2])#設置x坐標軸范圍 ax.set_ylim([-2, 2])#設置y坐標軸范圍 ax.set_xlabel('xxxxxxxxxxx')#設置x坐標軸名稱 ax.set_ylabel('yyyyyyyyyyy')#設置y坐標軸名稱 ticks = np.arange(-2, 2, 0.3) ax.set_xticks(ticks)#設置x軸刻度 ax.set_yticks(ticks)#設置y軸刻度 ax.axis('scaled')#設置坐標軸寬高等比於x、y范圍 ax.axis('image')#類似於scaled,暫時沒發現區別 ax.axis('off')#關閉坐標軸 ax.axis('equal')#圖像寬高比例不變,坐標軸范圍變 ax.axis('tight')#坐標軸緊緊貼合圖像,不設置默認就是這個 ax.axis('square')#設置坐標軸寬高比為1:1,坐標軸跨度取較大的那個
動態圖像
plt.cla()
ax.clear()
這兩個函數用於將子圖清空,配合暫停函數
plt.pause(0.1)
即可實現動態圖像。
二維圖像
contourf()和contour()
畫等高線圖。這兩個函數差一個字母,但用法一樣,區別如下:
使用方法:
ax.contourf(X, Y, Z, levels=10, alpha=0.5, cmap='jet')
X是生成網格的X坐標數組(二維數組array,或者matrix),Y是和X相同類型的Y坐標,Z是對應網格的每個格點的函數值數組(也是二維數組array,或者matrix),網格的生成是使用numpy庫中的meshgrid()函數。levels是圖像中等高線的數量,我這里設置為10。alpha是圖像的透明度,介於0~1,我這里設置為0.5半透明。可以設置透明度有個好處就是可以把很多圖畫在同一個畫布上,方便比較。cmap是圖像的顏色類型,有很多預設的顏色類型,我這里用一個叫‘jet’的顏色類型,當然也可以自己定義,具體設置網上再找吧。后三項有預設值,可以省略。
效果圖:
看起來不是很圓潤,這是因為我的網格規模就是7*7的,它畫圖就按照你的網格數量來畫,所以有棱有角的。有一點奇怪的就是,網格是有限的,它是怎么畫出這么多的等高線的?我猜它應該是線性插值插進去的。反正也就一個圖用來看的,不用特別准確。但是如果要准確怎么辦?那就把網格設置地密一些!別讓等高線的密度比網格的密度大太多就好了。
另外,可以用clabel()這個函數用來標注等高線圖的數值:
plt.clabel(C, inline=False, fontsize=12)
C代表剛剛畫的等高線圖(在用contour()等函數畫完以后傳給C,C = contour(...)),inline是否畫在線內,fontsize數字的大小。
plot()
ax.plot(x, y, ls="-", lw=2, label="plot figure", color='black',alpha=0.5...)
用來畫二維面上的點、線。當然也可以在三維的空間里面畫,就畫在三維坐標系的xOy面上。重要參數介紹:
x: 要畫的線的各個點在x軸上的坐標(一維數組)
y: 要畫的線的各個點在y軸上的坐標(一維數組或二維數組,第一維規模要和x軸的數組一致,第二維規模的大小就是畫線的數量)
ls:折線圖的線條風格,這里是一個減號
lw:折線圖的線條寬度
label:標記圖內容的標簽文本
color:顏色
alpha:透明度
還有很多的參數可以調節,這里不一一列舉,請看鏈接。另外,很多其它畫線的函數也都支持一些個性化的參數,比如color、alpha、width等等,參數匯總看鏈接。
bar()
ax.bar(range(len(values)), values)
繪制條形圖,第一個參數為橫坐標,第二個參數為橫坐標對應的值。
示例代碼:
import matplotlib.pyplot as plt import numpy as np values = np.random.normal(0,1,[20]) plt.bar(range(len(values)),values) plt.show()
hist()
ax.hist(data,bins=50,range=[-5,5],density=True,cumulative=True,rwidth=0.9,orientation = 'vertical')
畫頻次直方圖,這個函數會自動對數據做統計,如果是已經統計好的數據,可以使用上面的bar()函數畫圖。重要參數介紹:
x:待統計的一維數據。
bins:柱子的數量
range:數據統計的范圍
density:是否轉換為頻率密度圖(密度圖,乘以范圍寬度才是這個范圍內數據的頻率占比)
cumulative:是否累加,若為真,柱子統計的是小於等於這個值的所有數據。
rwidth:柱子的寬度。
orientation:柱子是垂直還是水平放置。
以下統計一個正態分布的累計柱狀圖:
hist2d()與hexbin()
ax.hist2d(x,y,bins=30,cmap='Blues')
二維頻次直方圖。參數與上述一維頻次直方圖類似。以下顯示二維正態分布抽樣頻次統計圖(旁邊的色度條是plt.colorbar(),子圖如何加還沒研究...):
ax.hexbin(x,y,gridsize=30,cmap='Blues')
就是方格變成六邊形格,gridsize表示格子大小:
繪制二維熱度圖
以上二維頻次直方圖函數會先對輸入做統計,再進行繪圖。如果是已經統計好的二維數據,我們可以用imshow()函數來畫。示例代碼如下:
import matplotlib.pyplot as plt values = np.random.randint(0,100,[5,5]) hot = plt.imshow(values, cmap=plt.cm.hot_r) #第二個參數是顏色風格 plt.colorbar(hot) #設置刻度條 plt.show()
三維圖像
建立三維坐標系
fig = plt.figure() #添加繪圖窗口 ax = fig.add_subplot(221,projection = '3d') #窗口內添加3d子圖 ax = fig.add_subplot(projection = '3d') #如果只畫一張圖,可以用這個
plot_surface()
ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, cmap='jet')
畫三維的曲面圖,並且帶有梯度顏色。
X、Y、Z就是每個網格點在對應坐標軸的值,cmap是塗色類型。rstride 是在行上每幾個網格點計算一次梯度來圖上對應梯度的顏色。cstride 就是列上的。它們越大,畫梯度顏色的“補丁”也越大,對應地,“補丁”的數量也越少。如下圖,一個是1,一個是2,“補丁”就一個是20,一個是10。
外部圖像
圖像導入與顯示
import matplotlib.pyplot as plt import pylab #原本在jupyter里才能顯示的圖片,可以用窗口顯示 img=plt.imread("image.jpg") #讀取圖片,讀取到的是:高度×寬度×3RGB 的array數組 fig = plt.figure() #創建窗口 ax = fig.add_subplot(111) #創建子圖 ax.imshow(img) #子圖中添加圖片 pylab.show() #顯示窗口
cv2
圖像批處理
從壓縮包中直接讀取圖片
import zipfile import cv2 import numpy as np import matplotlib.pyplot as plt path = 'D:/Datasets/dogs-vs-cats/train.zip'#壓縮包地址 with zipfile.ZipFile(path,mode='r') as f: for name in f.namelist(): if '.jpg' not in name: continue print(name) with f.open(name,mode='r') as image_file: content = image_file.read() # 讀取圖片 img = np.asarray(bytearray(content), dtype='uint8') #將jpg格式轉碼 img = cv2.imdecode(img, cv2.IMREAD_COLOR)#再轉化為BGR格式,注意不是RGB,順序反了 ,不重組的話在plt顏色顯示異常 b,g,r = cv2.split(img) img = cv2.merge([r,g,b]) #將BGR拆分再重組為RGB plt.imshow(img) plt.show() break
圖形拉伸
import cv2 cv2.resize(img,(w,h),interpolation=0)
將存在數組中的圖像拉伸成w寬,h高。interpolation=0表示最近鄰插值,不作平滑處理。其它插值參數(interpolation)請看鏈接。
seaborn
import seaborn as sns
seaborn簡化了matplotlib的繪圖操作,並且讓圖像更精美,繪制matplotlib圖像時,使用sns.set(),可讓圖像更具特色。
mayavi
import mayavi.mlab as mlab
mayavi是專門繪制三維圖形的庫,雖然matplotlib也能繪制,但是matplotlib並不支持光線追蹤,所以沒有遮擋的效果。繪制各種圖像的函數和matplotlib差不多。mayavi文檔、簡易實例。
mesh()
繪制三維圖形表面,用法和matplotlib的plot_surface類似,但是創建網格時推薦用mgrid,meshgrid的索引順序不對。
mlab.mesh(x, y, z )#繪制光滑表面 mlab.mesh(x, y, z, representation="wireframe", line_width=1.0)#繪制線而不是表面
下圖畫了一個卷起來的彩帶:
代碼如下:
import mayavi.mlab as mlab import numpy as np roll = 10 r = 0.5 w = 0.8 theta = np.linspace(np.pi*0.5,np.pi*2*roll,num=roll*100)[:,np.newaxis] h = np.linspace(-1,1,num=2)[np.newaxis,:]+0.5 x = y = z = np.zeros([len(theta),len(h[0,:])]) x = x + np.cos(theta)*theta*r/np.pi y = y + np.sin(theta)*theta*r/np.pi z = z + h - theta*w/np.pi print(y.shape,z.shape) mlab.mesh(x, y, z)#繪制光滑表面 mlab.show()
plot3d()
畫三維坐標系中的曲線。用法和matplotlib的plot類似。同樣推薦用mgrid創建網格。
mlab.plot3d(x,y,z)
numpy
用numpy的一些函數生成格式化的繪圖數據。
linspace()
linspace(a, b, n),傳回一個在a、b之間的插值列表(包括a、b),插值的數量是n。這個差值列表類型是array,而不是list,array里的數據類型是固定的,都是float。而列表list里面則並不是固定的,里面可以存任何東西。array是numpy下定義的一個類型,這個類型類似C++的數組,隨機查找很快。所以處理大批量同類數據的時候,最好使用array類型。
具體使用和其他參數:
https://www.cnblogs.com/antflow/p/7220798.html
meshgrid()
用於生成對應列表的網格(網格也是用列表存,二維網格是對每一維來說是二維列表,三維網格對每一維來說是三維列表),用於繪制梯度圖等。使用方法如下:
1. [X, Y] = meshgrid(x,y)或者python還支持X,Y = meshgrid(x,y),不加方括號也行,當然直接A = meshgrid(x,y),傳給一個值也行,就是后面不太好處理。
2. [X, Y] = meshgrid(x)與[X, Y] = meshgrid(x, x)是等同的
3. [X, Y, Z] = meshgrid(x, y, z)生成三維的網格
生成的網格索引順序在二維X、Y中是先Y再X,三維X、Y、Z中順序是Y、X、Z。例如,在三維網格中,如果要獲得x[2],y[7],z[3]位置的Y軸坐標,就是Y[7][2][3]。在二維網格中,如果要獲得x[2],y[7]位置的X軸坐標,就是X[7][2]。
下圖顯示8*3的網格的X的列表:
mgrid
與meshgrid類似,同樣能生成對應的網格。但是它並不是函數,而是以索引的形式使用的屬性,並且還可以生成類似的2維以上的網格。另外,它和meshgrid的不同之處在於它們生成的網格的索引方式是相反的。推薦使用mgrid,它更容易理解。以下是實例:
import numpy as np a = np.mgrid[0:10:2,0:10:1] print(a)
索引的第二個冒號傳入整數表示數的間隔,不包含最后一個數。傳入復整數表示數的個數,比如5j表示范圍內5個數,包含最后一個數。