Programming Computer Vision with Python (学习笔记二)
首先介紹跟圖像處理、顯示有關兩個庫:NumPy和Matplotlib,然后介紹增強圖像對比度的實現原理。
NumPy
NumPy是Python用于科學計算的基礎庫,提供了一些很有用的概念,如:N維數組對象,可用于表示向量、矩陣、圖像數據等,另外還包含了線性代數及其運算函數。NumPy的數組對象在本書示例中會被大量使用,它可以作諸如矩陣乘法、變換、向量乘法和正態化等運算,我們通過這些運算來實現圖像對齊、圖像分類、圖像扭轉等。
這是一個基礎庫,通常不需要額外安裝。
N維數組在NumPy中對應的數據類型是ndarry,有時使用別名array(即numpy.array)。但要注意的是,它與Python的內置類型array是兩回事,不要混淆,Python內置array類型只處理一維數組,其功能遠不及ndarray。ndarray中的所有元素的存儲類型是一樣的,下面對ndarray一些重要的屬性進行說明:
-
ndarray.ndim
數組維度 -
ndarray.shape
對于一個n×m矩陣,shape返回元組(n,m) -
ndarray.size
數組的所有元素個數
ndarray.dtype
數組元素的數據類型
-
ndarray.itemsize
數據中每個元素的類型長度(單位byte) -
ndarray.data
包含數組所有元素的buffer,通常我們只是使用數組下標來獲取元素的值
構造
用Python的數組表示來構造ndarray,很直觀:
構建dnarray時可以指定元素的類型:
In [12]: b = np.array([0,1,2],dtype=int16)In [13]: b.itemsize Out[13]: 2我們最常用的是想把一幅圖像轉為np.array表示,而PIL的Image類可以處理大部分的圖像格式,所以從Image轉為np.array很有用,如:
from PIL import Image import numpy as np im = np.array(Image.open('Selection_001.png'))注:Image對象之所以能直接轉為ndarray類型,是因為Image類實現了ndarray的data和shape等接口。
其它一些有用的構造方法:
-
np.zeros( (n, m) ) 構建n乘m數組,其中元素初始化為0
-
np.ones( (n, m) ) 同上,但元素初始化為1
-
np.empty( (n, m) ) 同上,但元素不作初始化
-
np.arange([start,] stop[, step,], dtype=None) 構建1維數組,元素的值從start到stop,增加步長為step
-
np.linspace( start, stop, item_count ) 構建1維數組,元素從start到stop,元素個數為item_count,所以元素的增加步長是自動計算的: (to - from) / (item_count - 1)
基本運算
兩個數組的+-<>*運算,作用于兩個數組相對應位置的元素,結果是一個新數組:
數組A與B的乘積:A.dot(B)或np.dot(A, B)。
對+=和*=等運算符產生的結果,直接修改調用數組自身,而不是返回新數組。
其它一些有用的運算操作:np.sin, np.cos, np.exp(指數), np.sqrt(開方)等。
下標訪問
In [45]: a Out[45]: array([[ 0, 1, 2, 3],[10, 11, 12, 13],[20, 21, 22, 23],[30, 31, 32, 33],[40, 41, 42, 43]])In [46]: a[2,3] #訪問行下標為2,列下標為3的元素 Out[46]: 23In [47]: a[0:5, 1] #訪問行下標從0到5(不含),列下標為1的元素 Out[47]: array([ 1, 11, 21, 31, 41])In [50]: a[:, 1] #訪問所有行,但列下標為1的元素 Out[50]: array([ 1, 11, 21, 31, 41])In [51]: a[1:3] #訪問行下標從1到3(不含)的元素 Out[51]: array([[10, 11, 12, 13],[20, 21, 22, 23]])In [52]: a[-1] #訪問最后一行 Out[52]: array([40, 41, 42, 43])In [2]: x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [3]: x[1:7:2] #指定起始、結束(不含)以及步長 Out[3]: array([1, 3, 5]) 變形
展開為一維數組:
有了以上的了解,我們來看看實際的應用例子。先讀取一張圖片,把它轉為ndarray類型,再看其數組屬性:
In [88]: from PIL import Image In [89]: import numpy as npIn [91]: im = np.array(Image.open('Selection_001.png')) #用PIL.Image讀取圖像,并轉為ndarray數組 In [92]: print im.shape, im.dtype (240, 568, 3) uint8 #表示圖像數據240行,568列,顏色通道數3,以uint8類型存儲In [93]: im_l = np.array(Image.open('Selection_001.png').convert('L')) #轉為灰度圖像 In [94]: print im_l.shape, im_l.dtype (240, 568) uint8 #灰度圖像沒有顏色通道信息 矩陣
class numpy.matrix(data, dtype=None, copy=True)
從data中構造一個矩陣對象,data可以是ndarray也可以是字符串,若data為ndarray,則copy表示是否復制data來構造。
還可以使用以下兩個函數來構造矩陣:
numpy.mat(data, dtype=None)或numpy.asmatrix(data, dtype=None),兩個只是名字不一樣,都相當于numpy.matrix(data, copy=False)。
矩陣類提供了一些矩陣運算的方便的接口,如:
getT:返回轉置矩陣
getI: 返回可逆矩陣的逆矩陣
getH:返回共軛轉置矩陣
getA:返回矩陣的ndarray
Matplotlib
Matplotlib是一個用于科學計算及制圖方面的強大的開源庫,支持很多常見的圖形圖表,如:
雖然Matplotlib功能很強大,我們可能只是用到它很少的一些接口,比如畫圖像的輪廓和灰度圖像的柱狀圖。
安裝Matplotlib
pylab和pyplot
為簡化畫圖工作,Matplotlib的pyplot模塊提供了與MATLAB相似的接口,并且可以跟IPython配合使用。
需要注意的是,書中的代碼示例使用的是Matplotlib.pylab這個模塊:
根據Matplotlib官網上的pyplot和pylab的關系說明得知:使用pylab只是為了import時方便起見,import pylab相當于import了pyplot和numpy模塊中大部分的接口,雖然有些例子還這樣用,但已經不被推薦使用,而是推薦使用pyplot。另外,pyplot模塊內置了狀態機,它能自動生成必要的圖例和坐標軸等信息,可以簡化畫圖代碼。
灰度變換(GrayLevel Transformation)
對圖像進行灰度變換的目的是為了:
-
改善畫質,使圖像更加清晰
-
有選擇地突出圖像中感興趣的特征或抑制圖像中某些不需要的特征,使圖像與視覺響應特性相匹配
-
改變圖像的直方圖分布,增加圖像對比度
最簡單的灰度變換就是反轉顏色,示例:
In [88]: from PIL import Image In [89]: import numpy as np In [90]: import matplotlib.pyplot as pltIn [97]: im = np.array(Image.open('cover.png').convert('L')) In [98]: plt.gray() #不加的話,顯示出來的圖像會有顏色 In [100]: plt.imshow(im) In [102]: plt.show()In [103]: im2 = 255 - im In [104]: plt.imshow(im2) In [105]: plt.show() 反轉前:
反轉后:
直方圖均衡化(histogram equalization)
灰度變換的一個很有用的例子就是直方圖均衡化,這里的直方圖指圖像的灰度直方圖,因為我們要示例的是灰度圖像,每個像素用8bit表示,值從0到255,共有256個灰度級。但通常的圖像像素值,都沒有完全占用這256個級別,很多像素的灰度值集中在一起,這樣導致灰度之間的變化不明顯,如果我們把圖像的灰度級按比例拉伸到256級,可以使得像素灰度級差距增大,從而使圖像看起來更清晰,對比度更強一些。直方圖均衡化就是為了達到這個目的,均衡化后的圖像,像素落在每個灰度級上的個數是相等的。而且原圖像的第i個灰度累積和(即落在[0,i]區間所有像素個數)與均衡化后的第i個灰度累積和相等,即原圖像累積和按0到255的比例進行變換。所以下面將使用累積分布函數(cumulative distribution function,簡稱cdf)。
直方圖數據的統計將借助numpy.histogram函數來獲得:
numpy.histogram(a, bins=10, range=None, normed=False, weights=None, density=None)傳入數組及直方圖的柱的數目(柱也可由X軸點的系列指定),統計落在各個柱區間的元素的個數。參數: a: 數組,需要扁平化 bins: bin指的是直方圖中的“柱”,取值對應X軸上的區間[x,y),此參數可選,傳入int表示等寬柱的數量,也支持非等寬柱的設置 range:(float, float),可選,指定柱的最低和最高值 normed:bool,可選,NumPy1.6棄用,建議使用density參數 density:bool,可選,False表示函數返回的是落在每個柱區間的元素的數量,若為True,函數返回的是由`概率密度分布函數`對每個柱計算出來的值返回值: hist:ndarray,如density參數所說 bin_edges:柱的邊界數組,length(hist) + 1,即X軸上柱之間的分割點形成的數組示例: In [8]: a = np.array([0,1,2,3,4]) In [9]: np.histogram(a, 5) Out[9]: (array([1, 1, 1, 1, 1]), #a中落在以下各個區間的元素的個數 array([ 0. , 0.8, 1.6, 2.4, 3.2, 4. ])) #柱的邊界(區間),自動均分In [10]: np.histogram(a, 5, density=True) Out[10]: (array([ 0.25, 0.25, 0.25, 0.25, 0.25]), #概率密度分布array([ 0. , 0.8, 1.6, 2.4, 3.2, 4. ]))而累積和的計算需要用到numpy.cumsum函數:
numpy.cumsum(a, axis=None, dtype=None, out=None) 示例: In [21]: a = np.array([1,2,3,4,5,6]) In [22]: np.cumsum(a) Out[22]: array([ 1, 3, 6, 10, 15, 21])現在來寫一個函數實現直方圖均衡化:
import numpy as np from PIL import Image import matplotlib.pyplot as pltdef histeq(im,nbr_bins=256):imhist,bins = np.histogram(im.flatten(),nbr_bins,density=True) #對每個元素求概率密度cdf = imhist.cumsum() #對概率密度數組求累積和cdf = 255 * cdf / cdf[-1] #累積和變換到0-255區間im2 = np.interp(im.flatten(),bins[:-1],cdf) #線性插值return im2.reshape(im.shape), cdf #還原圖像維度im = np.array(Image.open('hist-sample.jpg').convert('L')) im2,cdf = histeq(im)plt.gray() plt.subplot(221) #2行2列,第1個圖 plt.imshow(im) plt.subplot(222) #2行2列,第2個圖 plt.hist([x for x in im.flatten() if x < 250], 128) plt.subplot(223) plt.imshow(im2) plt.subplot(224) plt.hist([x for x in im2.flatten() if x < 250], 128) plt.show() 效果對比如下,上面的是原圖及直方圖,下面的是均衡化后的圖及直方圖:
明顯看出,均衡化后的圖對比度要更強一些。
多圖像平均法(Averaging Images)
多圖像平均法是一個用于降噪和美化圖片的簡單方法。假設多張圖像具有相同尺寸,一個計算方法就是把所有圖像的數據相加起來再除以圖像數目從而得到圖像的平均值。這個操作使用ndarray的+=和/=運算符就可以完成。
另一個實現的方法就是使用numpy.mean()函數,放在后面再講。
小結
下一個筆記內容講圖像的主成分分析(PCA)。
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Programming Computer Vision with Python (学习笔记二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Programming Computer
- 下一篇: Programming Computer