目錄
概論
算法原理
1、均值濾波
2、中值濾波
3、高斯濾波
4、雙邊濾波
5、引導(dǎo)濾波
?手寫代碼
Opencv代碼實(shí)現(xiàn)
?最后的總結(jié)
參考文章
概論
????????本來打算是分開推導(dǎo)的,但我覺得還是整個(gè)合集吧,避免有水文的嫌疑,那么因?yàn)閷W(xué)習(xí)的需要,會(huì)涉及到圖像的濾波處理,我匯總了一些常見的濾波算法,方便日后查看。
算法原理
1、均值濾波
????????我將以5*5的區(qū)域?yàn)槔觼碇v解:
此時(shí),中心點(diǎn)就很容易的被確定了,將所有的數(shù)全部加起來后,求取平均值取代中心點(diǎn)的中間值,但是圖像的邊界并不存在5*5的區(qū)域,那么只需要提取在圖像內(nèi)的周圍點(diǎn)的像素平均值。
附帶草稿圖:
均值濾波本身會(huì)存在缺陷,即他不能很好的保護(hù)好圖像的細(xì)節(jié),在圖像去噪的同時(shí)也破壞了圖像的細(xì)節(jié)部分,從而使圖像變得模糊,尤其是在處理椒鹽濾波的時(shí)候。?
2、中值濾波
????????其與中值濾波相似,同樣是選定固定的大小核,選取其中所有像素值的中位數(shù)作為濾波結(jié)果,類似的就是在比賽當(dāng)中,去掉最高分和最低分,其余分?jǐn)?shù)求取平均值,這個(gè)就叫做中位值平均濾波法,但這種方法就效率而言有點(diǎn)慢了。
附帶草稿圖:
3、高斯濾波
使用一個(gè)模板,常常稱為卷積或掩膜,來掃描圖像中的每一個(gè)像素,用模板確定的領(lǐng)域內(nèi)的像素的加權(quán)平均值去替代模板中心像素點(diǎn)的值。
附帶草稿:
在高斯濾波當(dāng)中,核的寬度和高度可以不相同,但都要是奇數(shù)。
同一尺寸的卷積核都可以有多種不同的形式,比如在下面的圖中5*5:
同一尺寸的卷積核可以有不同的權(quán)重比,在實(shí)際的計(jì)算當(dāng)中,卷積核是歸一化處理的,這種處理方式可以參考上面的3*3的卷積核(都是小數(shù)的),但有的資料當(dāng)中并沒有進(jìn)行歸一化,這時(shí)就可能是如我上圖當(dāng)中舉出來的5*5,7*7的卷積核,這樣的卷積核是為了說明問題用的,實(shí)際在用的時(shí)候還是需要進(jìn)行歸一化,準(zhǔn)確來說,沒有經(jīng)過歸一化的卷積核得到的結(jié)果往往是錯(cuò)誤的。
4、雙邊濾波
雙邊濾波是一種不同于以往的平滑濾波,是一種常用于像素邊緣保持的空間非線性濾波方法,主要利用了領(lǐng)域內(nèi)像素點(diǎn)的空間鄰近度和像素值相似度來構(gòu)建高斯權(quán)重濾波器。
附帶草稿圖:
?圖2:
5、引導(dǎo)濾波
引導(dǎo)濾波為何凱明等人于2010年提出,它本質(zhì)上具有O(N)復(fù)雜度,相當(dāng)于雙邊濾波有更好的邊緣保持特性,且不會(huì)出現(xiàn)梯度反轉(zhuǎn)的現(xiàn)象,在不同引導(dǎo)圖像的引導(dǎo)下,可廣泛應(yīng)用于降噪、去霧、高動(dòng)態(tài)范圍壓縮等。在其定義當(dāng)中,用到了局部線性模型,該模型認(rèn)為,某函數(shù)上一點(diǎn)與其鄰近部分的點(diǎn)成線性關(guān)系,一個(gè)復(fù)雜的函數(shù)就可以用很多局部的線性函數(shù)來表示,當(dāng)需要求該函數(shù)上某一點(diǎn)的值時(shí),只需計(jì)算所有包含該點(diǎn)的線性函數(shù)的值并作平均即可。
以下皆為對(duì)此的翻譯以及個(gè)人解釋:
GuidedFilter.dvi (kaiminghe.com)http://kaiminghe.com/publications/eccv10guidedfilter.pdf對(duì)于一個(gè)輸入圖像p,通過引導(dǎo)圖像I,經(jīng)過濾波后得到輸出圖像q,其中p和I都是算法的輸入。引導(dǎo)濾波定義了如下所示的一個(gè)線性濾波過程,對(duì)于i位置的像素點(diǎn),得到的濾波輸出是一個(gè)加權(quán)平均值:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?其中i和j分別表示像素的下標(biāo)。Wij是只和引導(dǎo)圖像I相關(guān)的濾波核。該濾波器相對(duì)于p是線性的,雙邊濾波核Wbf由下式給出:
? ? ? ? ? ? ? ? ? ? ? ? ?
其中x是像素坐標(biāo),Ki是規(guī)格化參數(shù),以確保Wij的和為1,參數(shù)σs和σr調(diào)整空間相似性和范圍(強(qiáng)度/顏色)相似性。聯(lián)合雙邊濾波器退化當(dāng)I和p相同時(shí),初始雙邊濾波器。
現(xiàn)在我們定義導(dǎo)向?yàn)V波器及其內(nèi)核。被引導(dǎo)者的關(guān)鍵假設(shè)濾波器是制導(dǎo)I和濾波器輸出q之間的局部線性模型。我們假設(shè)q是以像素k為中心的窗口ωk中I的線性變換:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?I
其中(ak,bk)是假定在ωk中為常數(shù)的一些線性系數(shù)。我們使用半徑為r的方形窗口。這種局部線性模型確保q有一條邊除非我有優(yōu)勢(shì),因?yàn)?q=a?I、 該模型已被證明在圖像消光、圖像超分辨率和煙霧消除。為了確定線性系數(shù),我們尋求上面式子的一個(gè)最小化的解q和濾波器輸入p之間的差值。具體來說,我們將窗口中的以下成本函數(shù):
? ? ? ? ? ? ? ? ? ? ? ??
?這里是一個(gè)正則化參數(shù),用于防止ak過大。上面的解可以通過線性回歸得出:
? ? ? ? ? ? ? ? ? ? ? ? ? ??
?這里,μ(k)和σ(k)**2是I在ωk中的平均值和方差,|ω|是ωk中的像素?cái)?shù),ˉpk是ωk中p的平均值。通過此修改?q不再是的縮放?一、 因?yàn)榫€性系數(shù)(ˉai,ˉbi)在空間上變化。但由于(ˉai,ˉbi)是平均濾波器的輸出,它們的梯度應(yīng)該比強(qiáng)邊附近的I小得多。在這種情況下,我們?nèi)匀豢梢?q≈ aˉ?I、 這意味著I中的突然強(qiáng)度變化大部分可以在q中保持。
?核重量可以明確表示為:
? ? ? ? ? ? ? ? ? ? ?
?
進(jìn)一步的計(jì)算表明和的Wij(I)=1。不需要額外努力以規(guī)范化權(quán)重。
對(duì)于該算法,當(dāng)I = p I=pI=p時(shí),即輸入圖像和引導(dǎo)圖像是同一副圖像時(shí),該算法即成為一個(gè)邊緣保持濾波器。同時(shí),方程的解也可作如下表示:? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?手寫代碼
本文只以手寫的中值濾波來實(shí)現(xiàn),其他的方法濾波器大家可以自己去嘗試以下:
import numpy as np
import cv2
def medianBlur(image, ksize=2):
rows, cols = image.shape[:2]
half = ksize // 2
start = half
end = rows-half-1
dst = np.zeros((rows, cols), dtype=np.uint8)
for y in range(start, end):
for x in range(start, end):
a = []
for i in range(y - half, y + half + 1):
for j in range(x - half, x + half + 1):
a.append(image[i][j])
# 取中間值
a = np.sort(a, axis=None)
if len(a) % 2 == 1:
medValue = a[len(a) // 2]
else:
medValue = int((a[len(a) // 2] + a[len(a) // 2 + 1]) / 2)
dst[y][x] = medValue
return dst
image = cv2.imread('Images/saltlena.png')
med = medianBlur(image)
# cv2.imwrite('Images/results/Med_image.png', med) #寫入
cv2.imshow('image',image)
cv2.imshow('Med_image',med)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值濾波效果展示:
Opencv代碼實(shí)現(xiàn)
import cv2
import numpy as np
def stackImages(scale,imgArray):
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range ( 0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
path = 'Images/Colnoiselena.jpg'
img=cv2.imread(path)
imgGray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgAverage=cv2.blur(img,(3,3)) #嘗試改變核的大小
imgMedianBlur=cv2.medianBlur(img,3) #可以修改核的大小
imgGaussianBlur=cv2.GaussianBlur(imgGray,(7,7),1.8)
imgBilater=cv2.bilateralFilter(img,9,75,75)
imgStack = stackImages(0.6,([img,imgGray,imgAverage],[imgMedianBlur,imgGaussianBlur,imgBilater]))
cv2.imshow("imges",imgStack)
cv2.waitKey(0)
效果圖:
在我運(yùn)行引導(dǎo)濾波的函數(shù)時(shí)出現(xiàn)了找不到模塊的問題:
AttributeError: 'cv2.ximgproc.GuidedFilter' object has no attribute 'shape'
可能是版本號(hào)的問題,有的函數(shù)可能申請(qǐng)了專利,由于我之前裝opencv的時(shí)候很麻煩,所以這里我找了別的大佬的代碼,大家可以看看。
詳細(xì)的引導(dǎo)濾波文章來源地址http://www.zghlxwxcb.cn/news/detail-467165.html
import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
R = 16 # 濾波半徑
r = 2 * R + 1
s = 1 # 快速引導(dǎo)濾波(如果大于0)
def read(path):
"""讀入圖片"""
src = cv.imread(path)
return src
def To_HSV(image):
"""轉(zhuǎn)化為HSV空間"""
dst = cv.cvtColor(image, cv.COLOR_BGR2HSV) # opencv是BGR模式
H, S, V = cv.split(dst)
cv.imshow('V', V)
return H, S, V
def To_BGR(H, S, V):
dst = cv.merge([H, S, V])
dst = cv.cvtColor(dst, cv.COLOR_HSV2BGR)
cv.imshow('dst', dst)
return dst
def LSE(V):
V_down = cv.resize(V, (V.shape[1] // s, V.shape[0] // s))
V_32 = V_down.astype(np.float32)
V_2 = np.square(V_32)
dst1 = cv.boxFilter(V_2, ddepth=-1, ksize=(r, r), normalize=True,
borderType=cv.BORDER_DEFAULT) # 盒式濾波(True為歸一化均值濾波),效率高之關(guān)鍵,類似積分圖
# print(dst1)
u_k = cv.boxFilter(V_32, ddepth=-1, ksize=(r, r), normalize=True,
borderType=cv.BORDER_DEFAULT) # 默認(rèn)為cv.BORDER_REFLECT101,鏡像
u_k_2 = np.square(u_k)
sigma_k = dst1 - u_k_2 # D(X)= E(X2)- E(X)2
print('最大方差為:', np.max(sigma_k)) # kesi的取值應(yīng)與此同量級(jí),以使方差發(fā)揮自適應(yīng)調(diào)節(jié)作用(ak公式)
kesi = 10000 # 重要參數(shù)(太小則全部保留梯度信息,沒有任何平滑(ak==1);太大則等價(jià)于均值濾波了)
a_k = (dst1 - u_k * u_k) / (sigma_k + kesi)
b_k = u_k - a_k * u_k
# print(a_k)
return a_k, b_k, V_down
def light(a_k, b_k, V_down, V):
a = cv.boxFilter(a_k, ddepth=-1, ksize=(r, r), normalize=True)
b = cv.boxFilter(b_k, ddepth=-1, ksize=(r, r), normalize=True)
I_down = a * V_down + b
# cv.imshow('I_down',I_down)
I = cv.resize(I_down, (V.shape[1], V.shape[0]))
I = np.where(I > 255, 255, I) # 可用clip函數(shù)
I = np.where(I < 0, 0, I)
I_ = I.astype(np.uint8)
cv.imshow('I', I_)
return I
if __name__ == '__main__':
path = 'Images/Colnoiselena.jpg' # 修改為自己路徑
src = read(path)
cv.imshow('src', src)
H, S, V = To_HSV(src)
ak, bk, V_down = LSE(V)
I = light(ak, bk, V_down, V)
cv.waitKey(0)
cv.destroyAllWindows()
?
?
?最后的總結(jié)
均值濾波:卷積核越大,圖片的失真越明顯,圖片會(huì)更模糊,如果設(shè)置核的大小為(1,1),則結(jié)果是原始圖像。
中值濾波:隨著核的增大,圖片會(huì)更加模糊,核必須是大于1的奇數(shù),如3,5,7等,在這cv2.medianBlur(src,ksize)當(dāng)中,填寫核時(shí)填寫一個(gè)數(shù)字,如3,5,7,在這里我們要對(duì)比均值濾波的用法。它對(duì)于椒鹽噪聲的圖片效果最好。
高斯濾波:隨著核的大小逐漸變大,會(huì)讓圖像更加模糊,核的大小(N,N)必須是大于1的奇數(shù),如3,5,7等,sigma表示的是X方向方差。我們常常在邊緣檢測(cè)中用到它。
雙邊濾波:具有平滑但保持邊緣的特性,而且雙邊濾波常常用在人像美化上,其他的比如上面的幾個(gè)都會(huì)將圖片變模糊。
引導(dǎo)濾波:相對(duì)于雙邊濾波最大的優(yōu)點(diǎn)是在于算法的復(fù)雜度與窗口的大小無關(guān),對(duì)于處理較為大型的圖片時(shí),在效率上有明顯的提升,同時(shí)引導(dǎo)濾波可以很好的克服雙邊濾波當(dāng)中的梯度翻轉(zhuǎn)的現(xiàn)象,它的線性的計(jì)數(shù)量,可以顯著的提高處理的效率。
參考文章
雙邊濾波——(博主)一蓑煙雨任平生~
高斯濾波——(博主)半濠春水
?Guided Image Filtering - Kaiming He文章來源:http://www.zghlxwxcb.cn/news/detail-467165.html
詳細(xì)的引導(dǎo)濾波
到了這里,關(guān)于圖像處理:推導(dǎo)五種濾波算法(均值、中值、高斯、雙邊、引導(dǎo))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!