图像降噪,也称图像去噪(Image denoising)。
滤波是图像降噪的一种方法,但降噪不是滤波的唯一应用场合。
图像噪声
常见图像噪声有以下四种:
高斯噪声 | 泊松噪声 |
乘性噪声 | 椒盐噪声 |
高斯噪声
高斯噪声,指概率密度函数服从高斯分布(即正态分布)的一类噪声。如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度又是均匀分布的,则称它为高斯白噪声。
泊松噪声
泊松噪声,指符合泊松分布的噪声模型。泊松分布适合描述单位时间内随机事件发生次数的概率分布。
乘性噪声
乘性噪声一般由信道不理想引起,它们与信号的关系是相乘的,信号在它在,信号不在时他也就不在了。
椒盐噪声
椒盐噪声,又称脉冲噪声,它随机改变一些像素值,是由图像传感器、传输信道、解码处理等产生的黑白相间的亮暗点噪声。
局部去噪
OpenCV中有多个可以降低图像噪声、对图像实现平滑滤波的函数,如
-
blur:对各种噪声都有一定的抑制作用
-
GaussianBlur:对随机噪声比较好,对椒盐噪声效果不好
-
medianBlur:对椒盐噪声效果比较好
具体可参见:图像滤波
非局部去噪
在滤波技术里,通常取像素周围的一小部分邻域进行平滑滤波。对于非局部去噪技术,OpenCV提供了四种变体:
使用单个灰度图像:
函数原型:
def fastNlMeansDenoising(src, dst=None, h=None, templateWindowSize=None, searchWindowSize=None)
使用单个彩色图像
函数原型:
def fastNlMeansDenoisingColored(src, dst=None, h=None, hColor=None, templateWindowSize=None, searchWindowSize=None)
通用参数:
-
h:值越大表示去噪声力度越大,同时细节丢失也越多,默认值为10
-
hColor:与h相同,但仅适用于彩色图像,大小通常与h相同
-
templateWindowSize:相似性权重计算窗口大小,一般为5~15之间的奇数
-
searchWindowSize:搜索窗口,大小可以设置为相似性计算窗口大小的3~5倍的奇数
使用在短时间内捕获的图像序列(灰度图像)
函数原型:
def fastNlMeansDenoisingMulti(srcImgs, imgToDenoiseIndex, temporalWindowSize, dst=None, h=None, templateWindowSize=None, searchWindowSize=None)
使用在短时间内捕获的图像序列(彩色图像)
函数原型:
def fastNlMeansDenoisingColoredMulti(srcImgs, imgToDenoiseIndex, temporalWindowSize, dst=None, h=None, hColor=None, templateWindowSize=None, searchWindowSize=None)
通用参数:
-
srcImgs:带噪点的图像帧的列表
-
imgToDenoiseIndex: 指定需要降噪的那一帧对应的索引。
-
temporalWindowSize:指定多少个周围的帧用来去噪,奇数。(如,传入5帧图像列表,imgToDenoiseIndex = 2, temporalWindowSize = 5,即使用第0~4帧,来给第2帧去噪)
去噪效果对比
import cv2
def get_srcImgs():
imgs = []
imgs_gray = []
videoCapture = cv2.VideoCapture("./test.mp4")
videoCapture.set(cv2.CAP_PROP_POS_FRAMES, 90)
for i in range(3):
success, img= videoCapture.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgs.append(img)
imgs_gray.append(gray)
return imgs, imgs_gray
def show_GaussianBlur(img):
gaussian = cv2.GaussianBlur(img, (5, 5), 0)
gaussian_Canny = cv2.Canny(gaussian, 42, 42 * 3, apertureSize=3)
cv2.imshow('gaussian kSize=5*5', gaussian)
cv2.imshow('gaussian_Canny', gaussian_Canny)
def denoise(x):
h = cv2.getTrackbarPos('h', 'denoise demo')
tempSize = cv2.getTrackbarPos('size', 'denoise demo')
searchSize = tempSize * 3
if tempSize % 2 == 0:
return
denoise_color = cv2.fastNlMeansDenoisingColored(img, None, h, h, tempSize, searchSize)
cv2.imshow('denoise color', denoise_color)
denoise = cv2.fastNlMeansDenoising(gray, None, h, tempSize, searchSize)
denoise_Canny = cv2.Canny(denoise, 42, 42 * 3, apertureSize=3)
cv2.imshow('denoise', denoise)
cv2.imshow('denoise_Canny', denoise_Canny)
denoise_color_Multi = cv2.fastNlMeansDenoisingColoredMulti(imgs, 1, 3, None, h, h, tempSize, searchSize)
cv2.imshow('denoise_color_Multi', denoise_color_Multi)
denoise_Multi = cv2.fastNlMeansDenoisingMulti(imgs_gray, 1, 3, None, h, tempSize, searchSize)
denoise_Multi_Canny = cv2.Canny(denoise_Multi, 42, 42 * 3, apertureSize=3)
cv2.imshow('denoise_Multi', denoise_Multi)
cv2.imshow('denoise_Multi_Canny', denoise_Multi_Canny)
h = 9
size = 9
imgs, imgs_gray = get_srcImgs()
img = cv2.imread("./frame_91.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.namedWindow('denoise demo')
cv2.imshow('denoise demo', img)
cv2.createTrackbar('h', 'denoise demo', h, 30, denoise)
cv2.createTrackbar('size', 'denoise demo', size, 15, denoise)
show_GaussianBlur(img)
denoise(0)
if cv2.waitKey(0) == 27:
cv2.destroyAllWindows()