摘要:首先介紹跟圖像處理顯示有關兩個庫和,然后介紹增強圖像對比度的實現原理。直方圖均衡化就是為了達到這個目的,均衡化后的圖像,像素落在每個灰度級上的個數是相等的。
首先介紹跟圖像處理、顯示有關兩個庫:NumPy和Matplotlib,然后介紹增強圖像對比度的實現原理。
NumPyNumPy是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,很直觀:
In [3]: import numpy as np In [5]: a = np.array([[0,1,2], [3,4,5]]) In [6]: a.shape Out[6]: (2, 3) In [7]: a.ndim Out[7]: 2 In [8]: a.dtype.name Out[8]: "int64" In [9]: a.itemsize Out[9]: 8 In [10]: a.size Out[10]: 6 In [11]: type(a) Out[11]: numpy.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
In [75]: np.arange(5) Out[75]: array([0, 1, 2, 3, 4]) In [76]: np.arange(5, 10) Out[76]: array([5, 6, 7, 8, 9]) In [77]: np.arange(5, 10, 2) Out[77]: array([5, 7, 9])
np.linspace( start, stop, item_count ) 構建1維數組,元素從start到stop,元素個數為item_count,所以元素的增加步長是自動計算的: (to - from) / (item_count - 1)
In [63]: np.linspace(5,10,2) Out[63]: array([ 5., 10.]) In [64]: np.linspace(5,10,3) Out[64]: array([ 5. , 7.5, 10. ]) In [65]: np.linspace(5,10,4) Out[65]: array([ 5. , 6.66666667, 8.33333333, 10. ]) In [66]: np.linspace(5,10,5) Out[66]: array([ 5. , 6.25, 7.5 , 8.75, 10. ])
基本運算
兩個數組的+-<>*運算,作用于兩個數組相對應位置的元素,結果是一個新數組:
In [22]: a Out[22]: array([[1, 2, 3], [4, 5, 6]]) In [23]: b Out[23]: array([[ 1., 1., 1.], [ 1., 1., 1.]]) In [24]: a + b Out[24]: array([[ 2., 3., 4.], [ 5., 6., 7.]]) In [25]: a - b Out[25]: array([[ 0., 1., 2.], [ 3., 4., 5.]]) In [26]: a < b Out[26]: array([[False, False, False], [False, False, False]], dtype=bool) In [30]: c Out[30]: array([[1, 1, 1], [2, 2, 2]]) In [31]: a * c Out[31]: array([[ 1, 2, 3], [ 8, 10, 12]])
數組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]: 23 In [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])
變形
展開為一維數組:
In [53]: a = np.array([[1,2],[3,4]]) #2乘2數組 In [54]: a Out[54]: array([[1, 2], [3, 4]]) In [57]: b = a.ravel() #展開為1維數組,返回新數組 In [58]: b Out[58]: array([1, 2, 3, 4]) In [59]: b.reshape(2, 2) #變形為2乘2數組,返回新數組 Out[59]: array([[1, 2], [3, 4]]) In [60]: b.resize(2, 2) #變形為2乘2數組,直接修改本身 In [61]: b Out[61]: array([[1, 2], [3, 4]])
有了以上的了解,我們來看看實際的應用例子。先讀取一張圖片,把它轉為ndarray類型,再看其數組屬性:
In [88]: from PIL import Image In [89]: import numpy as np In [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來構造。
In [4]: np.matrix("1 2; 3 4") Out[4]: matrix([[1, 2], [3, 4]]) In [5]: np.matrix([[1, 2], [3, 4]]) Out[5]: matrix([[1, 2], [3, 4]])
還可以使用以下兩個函數來構造矩陣:
numpy.mat(data, dtype=None)或numpy.asmatrix(data, dtype=None),兩個只是名字不一樣,都相當于numpy.matrix(data, copy=False)。
矩陣類提供了一些矩陣運算的方便的接口,如:
getT:返回轉置矩陣
getI: 返回可逆矩陣的逆矩陣
getH:返回共軛轉置矩陣
getA:返回矩陣的ndarray
Matplotlib是一個用于科學計算及制圖方面的強大的開源庫,支持很多常見的圖形圖表,如:
雖然Matplotlib功能很強大,我們可能只是用到它很少的一些接口,比如畫圖像的輪廓和灰度圖像的柱狀圖。
安裝Matplotlib
sudo apt-get install python-matplotlib
pylab和pyplot
為簡化畫圖工作,Matplotlib的pyplot模塊提供了與MATLAB相似的接口,并且可以跟IPython配合使用。
需要注意的是,書中的代碼示例使用的是Matplotlib.pylab這個模塊:
from PIL import Image from pylab import * im = array(Image.open("empire.jpg")) #讀圖并轉為ndarray imshow(im)
根據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 plt In [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()
反轉前:
反轉后:
灰度變換的一個很有用的例子就是直方圖均衡化,這里的直方圖指圖像的灰度直方圖,因為我們要示例的是灰度圖像,每個像素用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 plt def 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)。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44174.html
摘要:學習筆記七數學形態學關注的是圖像中的形狀,它提供了一些方法用于檢測形狀和改變形狀。學習筆記十一尺度不變特征變換,簡稱是圖像局部特征提取的現代方法基于區域圖像塊的分析。本文的目的是簡明扼要地說明的編碼機制,并給出一些建議。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 開始之前,我們先來看這樣一個提問: pyth...
摘要:接下來的學習筆記本人都將使用來代替。庫中提供的很多圖像操作都是分別作用于某個通道的數據。是最流行的開源色彩管理庫之一。目前只支持在增加和。模塊支持從圖像對象創建或的對象,方便被使用和顯示。模塊對圖像或指定區域的每個通道進行統計,包括等。 介紹 《Programming Computer Vision with Python》是一本介紹計算機視覺底層基本理論和算法的入門書,通過這本收可以...
摘要:下面是二維空間的高斯分布函數公式這個公式被稱作高斯核。高斯模糊使用高斯平均算子來實現的圖像模糊叫高斯模糊,也叫高斯平滑被認為是一種最優的圖像平滑處理。 SciPy庫 SciPy庫,與之前我們使用的NumPy和Matplotlib,都是scipy.org提供的用于科學計算方面的核心庫。相對NumPy,SciPy庫提供了面向更高層應用的算法和函數(其實也是基于NumPy實現的),并以子模塊...
摘要:簡稱庫是從擴展下來的,提供了更豐富的圖像處理函數,去噪函數除了還有算法,比如邊緣檢測還有以前簡單提過的算子濾波器。下面我用看具體的例子,將和高斯平滑進行對比效果對比如下明顯感覺使用的效果要比高斯平滑好很多。 圖像去噪(Image Denoising)的過程就是將噪點從圖像中去除的同時盡可能的保留原圖像的細節和結構。這里講的去噪跟前面筆記提過的去噪不一樣,這里是指高級去噪技術,前面提過的...
摘要:數學形態學關注的是圖像中的形狀,它提供了一些方法用于檢測形狀和改變形狀。所以這個結果也會把形狀以外的噪點排除掉。你還可以查看其它筆記。參考資料圖像的膨脹與腐蝕數學形態學基本操作及其應用計算機視覺特征提取與圖像處理第三版 數學形態學(mathematical morphology)關注的是圖像中的形狀,它提供了一些方法用于檢測形狀和改變形狀。起初是基于二值圖像提出的,后來擴展到灰度圖像。...
閱讀 1905·2021-11-24 11:16
閱讀 3260·2021-09-10 10:51
閱讀 3199·2021-08-03 14:03
閱讀 1266·2019-08-29 17:03
閱讀 3245·2019-08-29 12:36
閱讀 2232·2019-08-26 14:06
閱讀 497·2019-08-23 16:32
閱讀 2677·2019-08-23 13:42