目標(biāo)
- 學(xué)習(xí)使用非局部平均值去噪算法去除圖像中的噪音
- 學(xué)習(xí)函數(shù)cv2.fastNlMeansDenoising()、cv2.fastNlMeansDenoisingColored等
原理
????????在前面的章節(jié)中我們已經(jīng)學(xué)習(xí)了很多圖像平滑技術(shù),比如高斯平滑、中值平滑等。當(dāng)噪聲比較小時,這些技術(shù)的效果都是很好的。在這些技術(shù)中我們選取像素周圍一個小的鄰域然后用高斯平均值或者中值平均值取代中心像素。簡單來說,像素級別的噪聲去除是限制在局部領(lǐng)域的。
????????噪聲有一個性質(zhì)。我們認(rèn)為噪聲是平均值唯一的隨機(jī)變量??紤]一個帶噪聲的像素點p = p0 + n,其中p0 為像素的真實值,n 為這個像素的噪聲。我們可以從不同圖片中選取大量的相同像素(N)然后計算平均值。理想情況下我們會得到p = p0。因為噪聲的平均值為0。
? ? ? ? 通過簡單的設(shè)置我們就可以去除這些噪聲。將一個靜態(tài)攝像頭固定在一個位置連續(xù)拍攝幾秒。這樣我們就會得到足夠多的圖像幀或者同一場景的大量圖像。寫一段代碼求求解些幀的平均值(這對你來說應(yīng)該是小菜一碟)。將最終結(jié)果與第一幀圖像對比一下。你會發(fā)現(xiàn)噪聲減小了。不幸的是,種簡單的方法對于攝像頭和運動動場景并不總是適用。大多數(shù)情況下我們只有一張導(dǎo)游帶有噪音的圖像。
????????想法很簡單,我們需要一組相似的圖片,通過取平均值的方法可以去除噪音??紤]圖像中一個小的窗口(5x5)有很大可能圖像中的其它區(qū)域也存在一個相似的窗口。有時這個相似窗口就在鄰域周圍。如果我們找到這些相似的窗口并取他們的平均值會怎樣呢?對于特定的窗口這樣做挺好的。如下圖所示:
????????上圖中的藍(lán)色窗口看起來是相似的。綠色窗口看看來也是相似的。所以我們可以選取包含目標(biāo)像素的一個小窗口,然后在圖像中搜索相似的窗口,最后求取所有窗口的平均值,并用這個值取代目標(biāo)像素的值。這種方法就是非局部平均值去噪。與我們以前學(xué)習(xí)的平滑技術(shù)相比,種算法要消耗更多的時間,但是結(jié)果很好。你可以在更多資源中找到更多的細(xì)節(jié)和在線演示。對于彩色圖像首先要轉(zhuǎn)換到CIELAB 顏色空間,然后對L 和AB 成分分別去噪。?
OpenCV中的圖像去噪
OpenCV 提供了這種技術(shù)的四個變本。
- cv2.fastNlMeansDenoising() 使用對象為灰度圖。
- cv2.fastNlMeansDenoisingColored() 使用對象為彩色圖。
- cv2.fastNlMeansDenoisingMulti() 適用于短時的圖像序列(灰度圖像)
- cv2.fastNlMeansDenoisingColoredMulti() 適用于短時的圖像序列(彩色圖像)
????????共同參數(shù)有:
- h : 決定過濾器強(qiáng)度。h 值高可以很好的去除噪聲,但也會把圖像的細(xì)節(jié)抹去。(取10 的效果不錯)
- ?hForColorComponents : 與h 相同,但使用與彩色圖像。
- templateWindowSize : 奇數(shù)。(推薦值為7)
- searchWindowSize : 奇數(shù)。(推薦值為21)
????????下面演示一下2、3的效果:
和上面提到的一樣,cv2.fastNlMeansDenoisingColored()可以用來去除彩色圖像的噪聲。假設(shè)是高斯噪聲??:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('die.png')
dst = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(dst)
plt.show()
????????下面是結(jié)果的放大圖,我們的輸入圖像中含有方差為25 的噪聲,下面是結(jié)果:
????????現(xiàn)在我們使用cv2.fastNlMeansDenoisingMulti() 對一段視頻使用這個方法。第一個參數(shù)是一個噪聲幀的列表。第二個參數(shù)imgtoDenoiseIndex 設(shè)定哪些幀需要去噪,我們可以傳入一個幀的索引。第三個參數(shù)temporaWindowSize 可以設(shè)置用于去噪的相鄰幀的數(shù)目,它應(yīng)該是一個奇數(shù)。在這種情況下temporaWindowSize 幀的圖像會用于去噪,中間的幀就是要去噪的幀。例如,我們傳入5 幀圖像,imgToDenoiseIndex = 2 和temporalWindowSize = 3。那么第一幀、第二幀、第三幀圖像將將用于第二幀圖像的去噪。下面我們來看一個例子:
import numpy as np
import cv2
from matplotlib import pyplot as plt
cap = cv2.VideoCapture('vtest.avi')
# create a list of first 5 frames
img = [cap.read()[1] for i in xrange(5)]
# convert all to grayscale
gray = [cv2.cvtColor(i, cv2.COLOR_BGR2GRAY) for i in img]
# convert all to float64
gray = [np.float64(i) for i in gray]
# create a noise of variance 25
noise = np.random.randn(*gray[1].shape)*10
# Add this noise to images
noisy = [i+noise for i in gray]
# Convert back to uint8
noisy = [np.uint8(np.clip(i,0,255)) for i in noisy]
# Denoise 3rd frame considering all the 5 frames
dst = cv2.fastNlMeansDenoisingMulti(noisy, 2, 5, None, 4, 7, 35)
plt.subplot(131),plt.imshow(gray[2],'gray')
plt.subplot(132),plt.imshow(noisy[2],'gray')
plt.subplot(133),plt.imshow(dst,'gray')
plt.show()
????????計算消耗了相當(dāng)可觀的時間。第一張圖是原始圖像,第二個是帶噪音量圖像,第三個是去噪之后的圖像。?
?文章來源地址http://www.zghlxwxcb.cn/news/detail-810677.html文章來源:http://www.zghlxwxcb.cn/news/detail-810677.html
?
到了這里,關(guān)于OpenCV-Python(49):圖像去噪的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!