视觉/图像重磅干货,第一时间送达!
导 读
本文主要介绍如何用OpenCV实现开关中值滤波去除周期性线状噪声的实例,包含实现步骤和源码。
背景介绍
我们都知道中值滤波可以去除图像中的脉冲噪声或椒盐噪声,类似下图:
我们可以使用OpenCV提供的中值滤波函数就可以轻松将噪声滤除,并较好的保留图像边缘特征。
代码演示:
import cv2
import numpy as np
img=cv2.imread('snow.jpg',0)
cv2.imshow('src',img)
dst = cv2.medianBlur(img,3)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
3 x 3中值滤波效果:
那如果是线状的周期性噪声,还能用中值滤波吗?
实现步骤
下面的图片,不是离散的椒盐噪声,而是含有线状的周期性噪声:
我们还能直接用中值滤波去除上面的噪声么?先试试看!
3 x 3中值滤波效果(线条噪声仍存在):
5 x 5中值滤波效果(线条噪声少了,但是图像模糊了):
上面两种效果都不是我们想要的,那该怎么办呢?这里提供一种简单有效的方法,简称为开关中值滤波。
开关中值滤波器是先检测噪声像素,然后只对检测到的噪声像素进行中值滤波,而被判断为非噪声的像素则不再参与中值滤波。从而在滤除噪声的同时,较好的保留图像的细节。
实现步骤:
【1】检测噪声像素。依次遍历每一行,计算当前行的灰度值和,如果灰度值和大于100000,当前行判定为噪声行,置为0,否则为1。
def detect(img):
(w,h) = img.shape
flt = np.ones((w,h),dtype = int)
bright = []
for y in range(h):
bright.append(np.sum(img[:][y]))
x=np.arange(512)
plt.plot(x,bright,c='b')
plt.ylabel('Brightness')
plt.savefig('Brightness.jpg')
for i in range(h):
if bright[i]>100000:
flt[:][i]=0
return flt
【2】对噪声行的像素做中值滤波。下面代码演示的是对应噪声像素做均值滤波的结果,中值滤波需排序后取中值,效果类似。
def medianBlur(img):
(w,h) = img.shape
for i in range(2,w-1):
for j in range(2,h-1):
n = 0
s = 0
if img[i][j] == 0:
for ii in range(i-1,i+1):
for jj in range(j-1,j+1):
if img[ii][jj] != 0:
n = n + 1
s = s + img[ii][jj]
if n != 0:
img[i][j] = int(s/n)
return img
【3】调用测试与处理结果。
if __name__ == '__main__':
fileName = 'lena.jpg'
gray = cv2.imread(fileName,0)
cv2.imshow('src', gray)
flt = detect(gray)
grayWithoutNoise = gray*flt
mb = medianBlur(grayWithoutNoise)
mb = mb[1:512,1:512]
mb = np.array(mb,dtype=np.uint8)
cv2.imshow('result',mb)
cv2.waitKey(0)
cv2.destroyAllWindows()
总体来说,效果还不错。去除噪声的同时,较好的保留了细节。当然,还有其他实现方法,我们后续再介绍,敬请期待。
本文分享自 OpenCV与AI深度学习 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!