摘要:首先介紹跟圖像處理顯示有關(guān)兩個(gè)庫(kù)和,然后介紹增強(qiáng)圖像對(duì)比度的實(shí)現(xiàn)原理。直方圖均衡化就是為了達(dá)到這個(gè)目的,均衡化后的圖像,像素落在每個(gè)灰度級(jí)上的個(gè)數(shù)是相等的。
首先介紹跟圖像處理、顯示有關(guān)兩個(gè)庫(kù):NumPy和Matplotlib,然后介紹增強(qiáng)圖像對(duì)比度的實(shí)現(xiàn)原理。
NumPyNumPy是Python用于科學(xué)計(jì)算的基礎(chǔ)庫(kù),提供了一些很有用的概念,如:N維數(shù)組對(duì)象,可用于表示向量、矩陣、圖像數(shù)據(jù)等,另外還包含了線性代數(shù)及其運(yùn)算函數(shù)。NumPy的數(shù)組對(duì)象在本書示例中會(huì)被大量使用,它可以作諸如矩陣乘法、變換、向量乘法和正態(tài)化等運(yùn)算,我們通過這些運(yùn)算來實(shí)現(xiàn)圖像對(duì)齊、圖像分類、圖像扭轉(zhuǎn)等。
這是一個(gè)基礎(chǔ)庫(kù),通常不需要額外安裝。
N維數(shù)組在NumPy中對(duì)應(yīng)的數(shù)據(jù)類型是ndarry,有時(shí)使用別名array(即numpy.array)。但要注意的是,它與Python的內(nèi)置類型array是兩回事,不要混淆,Python內(nèi)置array類型只處理一維數(shù)組,其功能遠(yuǎn)不及ndarray。ndarray中的所有元素的存儲(chǔ)類型是一樣的,下面對(duì)ndarray一些重要的屬性進(jìn)行說明:
ndarray.ndim
數(shù)組維度
ndarray.shape
對(duì)于一個(gè)n×m矩陣,shape返回元組(n,m)
ndarray.size
數(shù)組的所有元素個(gè)數(shù)
ndarray.dtype
數(shù)組元素的數(shù)據(jù)類型
ndarray.itemsize
數(shù)據(jù)中每個(gè)元素的類型長(zhǎng)度(單位byte)
ndarray.data
包含數(shù)組所有元素的buffer,通常我們只是使用數(shù)組下標(biāo)來獲取元素的值
構(gòu)造
用Python的數(shù)組表示來構(gòu)造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
構(gòu)建dnarray時(shí)可以指定元素的類型:
In [12]: b = np.array([0,1,2],dtype=int16) In [13]: b.itemsize Out[13]: 2
我們最常用的是想把一幅圖像轉(zhuǎn)為np.array表示,而PIL的Image類可以處理大部分的圖像格式,所以從Image轉(zhuǎn)為np.array很有用,如:
from PIL import Image import numpy as np im = np.array(Image.open("Selection_001.png"))
注:Image對(duì)象之所以能直接轉(zhuǎn)為ndarray類型,是因?yàn)镮mage類實(shí)現(xiàn)了ndarray的data和shape等接口。
其它一些有用的構(gòu)造方法:
np.zeros( (n, m) ) 構(gòu)建n乘m數(shù)組,其中元素初始化為0
np.ones( (n, m) ) 同上,但元素初始化為1
np.empty( (n, m) ) 同上,但元素不作初始化
np.arange([start,] stop[, step,], dtype=None) 構(gòu)建1維數(shù)組,元素的值從start到stop,增加步長(zhǎng)為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 ) 構(gòu)建1維數(shù)組,元素從start到stop,元素個(gè)數(shù)為item_count,所以元素的增加步長(zhǎng)是自動(dòng)計(jì)算的: (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. ])
基本運(yùn)算
兩個(gè)數(shù)組的+-<>*運(yùn)算,作用于兩個(gè)數(shù)組相對(duì)應(yīng)位置的元素,結(jié)果是一個(gè)新數(shù)組:
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]])
數(shù)組A與B的乘積:A.dot(B)或np.dot(A, B)。
對(duì)+=和*=等運(yùn)算符產(chǎn)生的結(jié)果,直接修改調(diào)用數(shù)組自身,而不是返回新數(shù)組。
其它一些有用的運(yùn)算操作:np.sin, np.cos, np.exp(指數(shù)), np.sqrt(開方)等。
下標(biāo)訪問
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] #訪問行下標(biāo)為2,列下標(biāo)為3的元素 Out[46]: 23 In [47]: a[0:5, 1] #訪問行下標(biāo)從0到5(不含),列下標(biāo)為1的元素 Out[47]: array([ 1, 11, 21, 31, 41]) In [50]: a[:, 1] #訪問所有行,但列下標(biāo)為1的元素 Out[50]: array([ 1, 11, 21, 31, 41]) In [51]: a[1:3] #訪問行下標(biāo)從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] #指定起始、結(jié)束(不含)以及步長(zhǎng) Out[3]: array([1, 3, 5])
變形
展開為一維數(shù)組:
In [53]: a = np.array([[1,2],[3,4]]) #2乘2數(shù)組 In [54]: a Out[54]: array([[1, 2], [3, 4]]) In [57]: b = a.ravel() #展開為1維數(shù)組,返回新數(shù)組 In [58]: b Out[58]: array([1, 2, 3, 4]) In [59]: b.reshape(2, 2) #變形為2乘2數(shù)組,返回新數(shù)組 Out[59]: array([[1, 2], [3, 4]]) In [60]: b.resize(2, 2) #變形為2乘2數(shù)組,直接修改本身 In [61]: b Out[61]: array([[1, 2], [3, 4]])
有了以上的了解,我們來看看實(shí)際的應(yīng)用例子。先讀取一張圖片,把它轉(zhuǎn)為ndarray類型,再看其數(shù)組屬性:
In [88]: from PIL import Image In [89]: import numpy as np In [91]: im = np.array(Image.open("Selection_001.png")) #用PIL.Image讀取圖像,并轉(zhuǎn)為ndarray數(shù)組 In [92]: print im.shape, im.dtype (240, 568, 3) uint8 #表示圖像數(shù)據(jù)240行,568列,顏色通道數(shù)3,以u(píng)int8類型存儲(chǔ) In [93]: im_l = np.array(Image.open("Selection_001.png").convert("L")) #轉(zhuǎn)為灰度圖像 In [94]: print im_l.shape, im_l.dtype (240, 568) uint8 #灰度圖像沒有顏色通道信息
矩陣
class numpy.matrix(data, dtype=None, copy=True)
從data中構(gòu)造一個(gè)矩陣對(duì)象,data可以是ndarray也可以是字符串,若data為ndarray,則copy表示是否復(fù)制data來構(gòu)造。
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]])
還可以使用以下兩個(gè)函數(shù)來構(gòu)造矩陣:
numpy.mat(data, dtype=None)或numpy.asmatrix(data, dtype=None),兩個(gè)只是名字不一樣,都相當(dāng)于numpy.matrix(data, copy=False)。
矩陣類提供了一些矩陣運(yùn)算的方便的接口,如:
getT:返回轉(zhuǎn)置矩陣
getI: 返回可逆矩陣的逆矩陣
getH:返回共軛轉(zhuǎn)置矩陣
getA:返回矩陣的ndarray
Matplotlib是一個(gè)用于科學(xué)計(jì)算及制圖方面的強(qiáng)大的開源庫(kù),支持很多常見的圖形圖表,如:
雖然Matplotlib功能很強(qiáng)大,我們可能只是用到它很少的一些接口,比如畫圖像的輪廓和灰度圖像的柱狀圖。
安裝Matplotlib
sudo apt-get install python-matplotlib
pylab和pyplot
為簡(jiǎn)化畫圖工作,Matplotlib的pyplot模塊提供了與MATLAB相似的接口,并且可以跟IPython配合使用。
需要注意的是,書中的代碼示例使用的是Matplotlib.pylab這個(gè)模塊:
from PIL import Image from pylab import * im = array(Image.open("empire.jpg")) #讀圖并轉(zhuǎn)為ndarray imshow(im)
根據(jù)Matplotlib官網(wǎng)上的pyplot和pylab的關(guān)系說明得知:使用pylab只是為了import時(shí)方便起見,import pylab相當(dāng)于import了pyplot和numpy模塊中大部分的接口,雖然有些例子還這樣用,但已經(jīng)不被推薦使用,而是推薦使用pyplot。另外,pyplot模塊內(nèi)置了狀態(tài)機(jī),它能自動(dòng)生成必要的圖例和坐標(biāo)軸等信息,可以簡(jiǎn)化畫圖代碼。
灰度變換(GrayLevel Transformation)對(duì)圖像進(jìn)行灰度變換的目的是為了:
改善畫質(zhì),使圖像更加清晰
有選擇地突出圖像中感興趣的特征或抑制圖像中某些不需要的特征,使圖像與視覺響應(yīng)特性相匹配
改變圖像的直方圖分布,增加圖像對(duì)比度
最簡(jiǎn)單的灰度變換就是反轉(zhuǎn)顏色,示例:
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() #不加的話,顯示出來的圖像會(huì)有顏色 In [100]: plt.imshow(im) In [102]: plt.show() In [103]: im2 = 255 - im In [104]: plt.imshow(im2) In [105]: plt.show()
反轉(zhuǎn)前:
反轉(zhuǎn)后:
灰度變換的一個(gè)很有用的例子就是直方圖均衡化,這里的直方圖指圖像的灰度直方圖,因?yàn)槲覀円纠氖腔叶葓D像,每個(gè)像素用8bit表示,值從0到255,共有256個(gè)灰度級(jí)。但通常的圖像像素值,都沒有完全占用這256個(gè)級(jí)別,很多像素的灰度值集中在一起,這樣導(dǎo)致灰度之間的變化不明顯,如果我們把圖像的灰度級(jí)按比例拉伸到256級(jí),可以使得像素灰度級(jí)差距增大,從而使圖像看起來更清晰,對(duì)比度更強(qiáng)一些。直方圖均衡化就是為了達(dá)到這個(gè)目的,均衡化后的圖像,像素落在每個(gè)灰度級(jí)上的個(gè)數(shù)是相等的。而且原圖像的第i個(gè)灰度累積和(即落在[0,i]區(qū)間所有像素個(gè)數(shù))與均衡化后的第i個(gè)灰度累積和相等,即原圖像累積和按0到255的比例進(jìn)行變換。所以下面將使用累積分布函數(shù)(cumulative distribution function,簡(jiǎn)稱cdf)。
直方圖數(shù)據(jù)的統(tǒng)計(jì)將借助numpy.histogram函數(shù)來獲得:
numpy.histogram(a, bins=10, range=None, normed=False, weights=None, density=None) 傳入數(shù)組及直方圖的柱的數(shù)目(柱也可由X軸點(diǎn)的系列指定),統(tǒng)計(jì)落在各個(gè)柱區(qū)間的元素的個(gè)數(shù)。 參數(shù): a: 數(shù)組,需要扁平化 bins: bin指的是直方圖中的“柱”,取值對(duì)應(yīng)X軸上的區(qū)間[x,y),此參數(shù)可選,傳入int表示等寬柱的數(shù)量,也支持非等寬柱的設(shè)置 range:(float, float),可選,指定柱的最低和最高值 normed:bool,可選,NumPy1.6棄用,建議使用density參數(shù) density:bool,可選,F(xiàn)alse表示函數(shù)返回的是落在每個(gè)柱區(qū)間的元素的數(shù)量,若為True,函數(shù)返回的是由`概率密度分布函數(shù)`對(duì)每個(gè)柱計(jì)算出來的值 返回值: hist:ndarray,如density參數(shù)所說 bin_edges:柱的邊界數(shù)組,length(hist) + 1,即X軸上柱之間的分割點(diǎn)形成的數(shù)組 示例: 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中落在以下各個(gè)區(qū)間的元素的個(gè)數(shù) array([ 0. , 0.8, 1.6, 2.4, 3.2, 4. ])) #柱的邊界(區(qū)間),自動(dòng)均分 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. ]))
而累積和的計(jì)算需要用到numpy.cumsum函數(shù):
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])
現(xiàn)在來寫一個(gè)函數(shù)實(shí)現(xiàn)直方圖均衡化:
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) #對(duì)每個(gè)元素求概率密度 cdf = imhist.cumsum() #對(duì)概率密度數(shù)組求累積和 cdf = 255 * cdf / cdf[-1] #累積和變換到0-255區(qū)間 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個(gè)圖 plt.imshow(im) plt.subplot(222) #2行2列,第2個(gè)圖 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()
效果對(duì)比如下,上面的是原圖及直方圖,下面的是均衡化后的圖及直方圖:
明顯看出,均衡化后的圖對(duì)比度要更強(qiáng)一些。
多圖像平均法(Averaging Images)多圖像平均法是一個(gè)用于降噪和美化圖片的簡(jiǎn)單方法。假設(shè)多張圖像具有相同尺寸,一個(gè)計(jì)算方法就是把所有圖像的數(shù)據(jù)相加起來再除以圖像數(shù)目從而得到圖像的平均值。這個(gè)操作使用ndarray的+=和/=運(yùn)算符就可以完成。
另一個(gè)實(shí)現(xiàn)的方法就是使用numpy.mean()函數(shù),放在后面再講。
下一個(gè)筆記內(nèi)容講圖像的主成分分析(PCA)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44174.html
摘要:學(xué)習(xí)筆記七數(shù)學(xué)形態(tài)學(xué)關(guān)注的是圖像中的形狀,它提供了一些方法用于檢測(cè)形狀和改變形狀。學(xué)習(xí)筆記十一尺度不變特征變換,簡(jiǎn)稱是圖像局部特征提取的現(xiàn)代方法基于區(qū)域圖像塊的分析。本文的目的是簡(jiǎn)明扼要地說明的編碼機(jī)制,并給出一些建議。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 開始之前,我們先來看這樣一個(gè)提問: pyth...
摘要:接下來的學(xué)習(xí)筆記本人都將使用來代替。庫(kù)中提供的很多圖像操作都是分別作用于某個(gè)通道的數(shù)據(jù)。是最流行的開源色彩管理庫(kù)之一。目前只支持在增加和。模塊支持從圖像對(duì)象創(chuàng)建或的對(duì)象,方便被使用和顯示。模塊對(duì)圖像或指定區(qū)域的每個(gè)通道進(jìn)行統(tǒng)計(jì),包括等。 介紹 《Programming Computer Vision with Python》是一本介紹計(jì)算機(jī)視覺底層基本理論和算法的入門書,通過這本收可以...
摘要:下面是二維空間的高斯分布函數(shù)公式這個(gè)公式被稱作高斯核。高斯模糊使用高斯平均算子來實(shí)現(xiàn)的圖像模糊叫高斯模糊,也叫高斯平滑被認(rèn)為是一種最優(yōu)的圖像平滑處理。 SciPy庫(kù) SciPy庫(kù),與之前我們使用的NumPy和Matplotlib,都是scipy.org提供的用于科學(xué)計(jì)算方面的核心庫(kù)。相對(duì)NumPy,SciPy庫(kù)提供了面向更高層應(yīng)用的算法和函數(shù)(其實(shí)也是基于NumPy實(shí)現(xiàn)的),并以子模塊...
摘要:簡(jiǎn)稱庫(kù)是從擴(kuò)展下來的,提供了更豐富的圖像處理函數(shù),去噪函數(shù)除了還有算法,比如邊緣檢測(cè)還有以前簡(jiǎn)單提過的算子濾波器。下面我用看具體的例子,將和高斯平滑進(jìn)行對(duì)比效果對(duì)比如下明顯感覺使用的效果要比高斯平滑好很多。 圖像去噪(Image Denoising)的過程就是將噪點(diǎn)從圖像中去除的同時(shí)盡可能的保留原圖像的細(xì)節(jié)和結(jié)構(gòu)。這里講的去噪跟前面筆記提過的去噪不一樣,這里是指高級(jí)去噪技術(shù),前面提過的...
摘要:數(shù)學(xué)形態(tài)學(xué)關(guān)注的是圖像中的形狀,它提供了一些方法用于檢測(cè)形狀和改變形狀。所以這個(gè)結(jié)果也會(huì)把形狀以外的噪點(diǎn)排除掉。你還可以查看其它筆記。參考資料圖像的膨脹與腐蝕數(shù)學(xué)形態(tài)學(xué)基本操作及其應(yīng)用計(jì)算機(jī)視覺特征提取與圖像處理第三版 數(shù)學(xué)形態(tài)學(xué)(mathematical morphology)關(guān)注的是圖像中的形狀,它提供了一些方法用于檢測(cè)形狀和改變形狀。起初是基于二值圖像提出的,后來擴(kuò)展到灰度圖像。...
閱讀 1917·2021-11-24 11:16
閱讀 3265·2021-09-10 10:51
閱讀 3217·2021-08-03 14:03
閱讀 1272·2019-08-29 17:03
閱讀 3253·2019-08-29 12:36
閱讀 2239·2019-08-26 14:06
閱讀 502·2019-08-23 16:32
閱讀 2695·2019-08-23 13:42