目錄
前言
概念介紹
基本原理
Opencv實(shí)現(xiàn)均值濾波
Python手寫(xiě)實(shí)現(xiàn)均值濾波
參考文章
前言
在此之前,我曾在此篇中推導(dǎo)過(guò)圖像處理:推導(dǎo)五種濾波算法(均值、中值、高斯、雙邊、引導(dǎo))。這在此基礎(chǔ)上,我想更深入地研究和推導(dǎo)這些算法,以便為將來(lái)處理圖像的項(xiàng)目打下基礎(chǔ)。
概念介紹
均值濾波是一種簡(jiǎn)單的圖像平滑處理方法,其基本思想是用像素點(diǎn)周圍的鄰域像素的平均值來(lái)代替該像素的值。在圖像處理中,均值濾波可以用于去除圖像中的噪聲,使圖像變得更加平滑。它的計(jì)算簡(jiǎn)單易懂,但在濾波過(guò)程中可能會(huì)導(dǎo)致圖像細(xì)節(jié)的損失。因此,在實(shí)際應(yīng)用中,需要根據(jù)具體的情況選擇適合的濾波算法。
基本原理
我們以5x5大小為例,均值濾波的原理只需要理解到,它其實(shí)是將這個(gè)范圍內(nèi)的25個(gè)值進(jìn)行求和的平均值,以這個(gè)新值來(lái)代替這個(gè)區(qū)域的中心值。
配合這里的圖進(jìn)行理解:
?右圖是經(jīng)過(guò)左圖進(jìn)行均值變換后的值。
print((197+25+106+156+159+149+40+107+17+71+163+198+226+223+156+222+37+68+193+157+42+72+250+41+75)/25)
運(yùn)行之后,獲得新值126,覆蓋掉中心值得像素226。
對(duì)于邊緣像素,只僅僅計(jì)算在這個(gè)范圍內(nèi)得數(shù)值。
假如,左上角為中心值,而其左邊和上邊都沒(méi)有值,我們只需要計(jì)算在這5x5區(qū)域內(nèi)有的值就可以了。
計(jì)算如下:
print((23+0+25+158+140+238+67+199+197)/9)
得出新值為116,替換中心點(diǎn)23的值。
Opencv實(shí)現(xiàn)均值濾波
def blur(src, ksize, dst=None, anchor=None, borderType=None):
在OpenCV中,我們可以使用cv2.blur()函數(shù)來(lái)實(shí)現(xiàn)均值濾波。在使用該函數(shù)時(shí),我們需要輸入原始圖像、濾波核的大小以及邊界樣式等參數(shù)。一般情況下,我們可以直接采用函數(shù)默認(rèn)值即可。
這里我拿的是我個(gè)人的一個(gè)使用情況來(lái)看待的,像錨點(diǎn),邊界樣式這種,我基本上沒(méi)有遇到要修改的情況,現(xiàn)在我們來(lái)看看濾波核的大小對(duì)圖片的影響。
import cv2
import pyps.pyzjr.utility as zjr
path = 'Images/Colnoiselena.jpg'
img = cv2.imread(path)
imgAverage_1 = cv2.blur(img, (1, 1))
imgAverage_3 = cv2.blur(img, (3, 3))
imgAverage_5 = cv2.blur(img, (5, 5))
imgAverage_7 = cv2.blur(img, (7, 7))
imgStack = zjr.stackImages(0.6, ([imgAverage_1, imgAverage_3], [imgAverage_5, imgAverage_7]))
cv2.imshow("imges",imgStack)
cv2.waitKey(0)
實(shí)現(xiàn)效果:
經(jīng)典的lena的圖片,可以看到,隨著濾波核的大小逐漸增加,去噪效果越好,但相應(yīng)的圖片會(huì)變的模糊,計(jì)算時(shí)間會(huì)增長(zhǎng)。所以,還是應(yīng)了我開(kāi)頭就說(shuō)過(guò)的話,在實(shí)際處理中,選擇合適的濾波核大小,讓模糊與去噪效果之間取得平衡。
pyps并不是什么第三方庫(kù),只是我集成在一起的函數(shù)文件,你無(wú)需在意。
Python手寫(xiě)實(shí)現(xiàn)均值濾波
import cv2
import numpy as np
import pyps.pyzjr.utility as zjr
path = 'Images/Colnoiselena.jpg'
img = cv2.imread(path)
def Arerage_Filtering(img, k_size=3):
if k_size % 2 == 0:
k_size += 1
rows, cols = img.shape[:2]
pad_width = (k_size - 1) // 2
img_pad = cv2.copyMakeBorder(img, pad_width, pad_width, pad_width, pad_width, cv2.BORDER_REPLICATE)
img_filter = np.zeros_like(img)
for i in range(rows):
for j in range(cols):
pixel_values = img_pad[i:i+k_size, j:j+k_size].flatten()
img_filter[i, j] = np.mean(pixel_values)
return img_filter
imgAverage_1 = Arerage_Filtering(img,k_size=1)
imgAverage_3 = Arerage_Filtering(img,k_size=3)
imgAverage_5 = Arerage_Filtering(img,k_size=5)
imgAverage_7 = Arerage_Filtering(img,k_size=7)
imgStack = zjr.stackImages(0.6, ([imgAverage_1, imgAverage_3], [imgAverage_5, imgAverage_7]))
cv2.imshow("imges",imgStack)
cv2.waitKey(0)
cv2.destroyAllWindows()
這個(gè)算法相對(duì)來(lái)說(shuō)比較容易實(shí)現(xiàn),但是相比調(diào)用OpenCV的函數(shù),它的計(jì)算時(shí)間要長(zhǎng)很多,而且我這里還只考慮了圖像的兩個(gè)通道,最終輸出的結(jié)果是灰度圖的情況下。
下面是這個(gè)函數(shù)的具體實(shí)現(xiàn)過(guò)程:
- 首先,判斷卷積核的大小是否為奇數(shù),如果為偶數(shù),則將其加1,確保其大小為奇數(shù)。
- 獲取圖像的行數(shù)和列數(shù)。
- 計(jì)算填充的寬度,即卷積核寬度的一半,用于處理圖像邊緣。
- 使用cv2.copyMakeBorder函數(shù)進(jìn)行邊緣填充,將圖像的邊緣復(fù)制并填充到周圍,以防止邊緣像素點(diǎn)無(wú)法進(jìn)行卷積。
- 初始化一個(gè)和原始圖像大小一樣的零矩陣。
- 遍歷圖像中的每一個(gè)像素點(diǎn),計(jì)算該像素點(diǎn)周圍鄰域內(nèi)的像素值,并求取其平均值,然后將其賦值給零矩陣中的對(duì)應(yīng)像素點(diǎn)。
- 返回處理后的圖像。
最后,函數(shù)通過(guò)stackImages函數(shù)將處理后的四張圖像以2x2的網(wǎng)格形式拼接成一張圖像,并展示結(jié)果。
參考文章
(6條消息) 圖像處理:推導(dǎo)五種濾波算法(均值、中值、高斯、雙邊、引導(dǎo))_高斯濾波,均值濾波,中值濾波_夏天是冰紅茶的博客-CSDN博客
(6條消息) 均值濾波(Mean filtering)_半濠春水的博客-CSDN博客文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-422844.html
(7條消息) Opencv之圖像濾波:2.均值濾波(cv2.blur)_Justth.的博客-CSDN博客文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-422844.html
到了這里,關(guān)于圖像處理:均值濾波算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!