Python 可視化與圖像處理


  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個數,包含最后一個數。

特定圖像樣例

  https://www.runoob.com/w3cnote/matplotlib-tutorial.html

  https://blog.csdn.net/jasonzhoujx/article/details/81780774


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM