OpenCV-Python 圖像去噪 | 五十九


作者|OpenCV-Python Tutorials
編譯|Vincent
來源|OpenCV-Python Tutorials

目標

在本章中,

  • 你將學習用於去除圖像中噪聲的非局部均值去噪算法。
  • 你將看到不同的函數,例如cv.fastNlMeansDenoising(),cv.fastNlMeansDenoisingColored()等。

理論

在前面的章節中,我們已經看到了許多圖像平滑技術,例如高斯模糊,中值模糊等,它們在某種程度上可以消除少量噪聲。在這些技術中,我們在像素周圍采取了一個較小的鄰域,並進行了一些操作,例如高斯加權平均值,值的中位數等來替換中心元素。簡而言之,在像素處去除噪聲是其周圍的局部現象。
有噪聲的性質。

通常認為噪聲是零均值的隨機變量。考慮一個有噪聲的像素,\(p=p_0+n\),其中\(p_0\)是像素的真實值,\(n\)是該像素中的噪聲。你可以從不同的圖像中獲取大量相同的像素(例如N)並計算其平均值。理想情況下,由於噪聲的平均值為零,因此應該得到\(p = p_0\)

你可以通過簡單的設置自己進行驗證。將靜態相機固定在某個位置幾秒鍾。這將為你提供很多幀或同一場景的很多圖像。然后編寫一段代碼,找到視頻中所有幀的平均值(這對你現在應該太簡單了)。
比較最終結果和第一幀。你會看到噪聲減少。不幸的是,這種簡單的方法對攝像機和場景的運動並不穩健。通常,只有一張嘈雜的圖像可用。

因此想法很簡單,我們需要一組相似的圖像來平均噪聲。考慮圖像中的一個小窗口(例如5x5窗口)。
很有可能同一修補程序可能位於圖像中的其他位置。有時在它周圍的一個小社區中。一起使用這些相似的補丁並找到它們的平均值怎么辦?對於那個特定的窗口,這很好。請參閱下面的示例圖片:

圖像中的藍色補丁看起來很相似。綠色補丁看起來很相似。因此,我們獲取一個像素,在其周圍獲取一個小窗口,在圖像中搜索相似的窗口,對所有窗口求平均,然后用得到的結果替換該像素。此方法是“非本地均值消噪”。與我們之前看到的模糊技術相比,它花費了更多時間,但是效果非常好。更多信息和在線演示可在其他資源的第一個鏈接中找到。

對於彩色圖像,圖像將轉換為CIELAB色彩空間,然后分別對L和AB分量進行降噪。

OpenCV中的圖像去噪

OpenCV提供了此方法的四個變體。

  1. cv.fastNlMeansDenoising()-處理單個灰度圖像
  2. cv.fastNlMeansDenoisingColored()-處理彩色圖像。
  3. cv.fastNlMeansDenoisingMulti()-處理在短時間內捕獲的圖像序列(灰度圖像)
  4. cv.fastNlMeansDenoisingColoredMulti()-與上面相同,但用於彩色圖像。

常用參數為:

  • h:決定濾波器強度的參數。較高的h值可以更好地消除噪點,但同時也可以消除圖像細節。(可以設為10)
  • hForColorComponents:與h相同,但僅用於彩色圖像。(通常與h相同)
  • templateWindowSize:應為奇數。(建議設為7)
  • searchWindowSize:應為奇數。(建議設為21)

請訪問其他資源中的第一個鏈接,以獲取有關這些參數的更多詳細信息。
我們將在此處演示2和3。剩下的留給你。

  1. cv.fastNlMeansDenoisingColored()

如上所述,它用於消除彩色圖像中的噪點。(噪聲可能是高斯的)。請參閱以下示例:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('die.png')
dst = cv.fastNlMeansDenoisingColored(img,None,10,10,7,21)
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(dst)
plt.show()

以下是結果的放大版本。我的輸入圖像的高斯噪聲為\(σ= 25\)。查看結果:

  1. cv.fastNlMeansDenoisingMulti()

現在,我們將對視頻應用相同的方法。第一個參數是噪聲幀列表。第二個參數imgToDenoiseIndex指定我們需要去噪的幀,為此,我們在輸入列表中傳遞幀的索引。第三是temporalWindowSize,它指定要用於降噪的附近幀的數量。應該很奇怪。在那種情況下,總共使用temporalWindowSize幀,其中中心幀是要被去噪的幀。例如,你傳遞了一個5幀的列表作為輸入。令imgToDenoiseIndex = 2,temporalWindowSize =3。然后使用frame-1frame-2frame-3去噪frame-2。讓我們來看一個例子。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
cap = cv.VideoCapture('vtest.avi')
# 創建5個幀的列表
img = [cap.read()[1] for i in xrange(5)]
# 將所有轉化為灰度
gray = [cv.cvtColor(i, cv.COLOR_BGR2GRAY) for i in img]
# 將所有轉化為float64
gray = [np.float64(i) for i in gray]
# 創建方差為25的噪聲
noise = np.random.randn(*gray[1].shape)*10
# 在圖像上添加噪聲
noisy = [i+noise for i in gray]
# 轉化為unit8
noisy = [np.uint8(np.clip(i,0,255)) for i in noisy]
# 對第三幀進行降噪
dst = cv.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()

計算需要花費大量時間。結果,第一個圖像是原始幀,第二個是噪聲幀,第三個是去噪圖像。

附加資源

  1. http://www.ipol.im/pub/art/2011/bcm_nlm/ (它包含詳細信息,在線演示等。強烈建議訪問。我們的測試圖像是從此鏈接生成的)
  2. Online course at coursera (這里拍攝的第一張圖片)

練習


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM