OpenCV---005(图像滤波(1))
图像滤波(1)
在图像采集的过程中可能会产生很多的噪声,所以对图像滤波是图像预处理中重要的一步
原图像:

图像卷积
卷积常用在信号处理中 图像信息可以看为一种信号 对于图像的卷积
给出一个卷积模板,然后再原图像种进行卷积计算 可以看为一个卷积模板
在原图像上进行移动 后对卷积模板覆盖范围进行计算并求和作为中心像素的
输出值。在原图像上由左到右 由上到下进行卷积计算 卷积模板被称为卷积核
是一个固定大小的矩阵
图像卷积可以分为五步:
1.模板旋转180度 由于绝大多数的卷积模板是对称的,所以大多数情况可以省略
2.将卷积模板放在原图像中需要卷积的地方
3.卷积模板的系数乘像素值 后求和得到值
4.将结果放在 原图像卷积模板中心对应的位置
5.将卷积模板左到右 上到下移动 到全部
(但是只能对原图像的中心区域进行卷积)
为了解决边缘问题,将图像扩大一圈0
因为卷积的原因 最后的像素点值可能越界 所以进行归一化
让卷积模板的全部值和为1
opencv提供函数:
dst = cv.fitlter2D(src,ddepth,kernel,[borderType])
ddepth 输出图像的深度
kernel 卷积核 多为 3*3 5*5
borderType 边缘外扩方法选择
点击查看代码
import cv2 as cv
import numpy as np
import sys
if __name__ == '__main__':
kernel1 = np.array([[1] * 3 for i in range(3)], dtype='float32')
kernel1 = kernel1 / 9
img = cv.imread('../preview.jpg', )
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
if img is None:
print('读取失败')
sys.exit()
res = cv.filter2D(img, -1, kernel=kernel1)
cv.imshow('old', img)
cv.imshow('ker', res)
cv.waitKey(0)
cv.destroyAllWindows()
噪声的种类和生成
常见的噪音有四种 分别为椒盐噪音 高斯噪音 乘性噪音 泊松噪音
椒盐噪音:
又被叫做脉冲噪音,随机改变图像中像素点的像素值 产生黑白的颗粒
生成方法:
output = np.random.randint(low,high,size,dtype)
椒盐噪音为随机的 所以直接用np的random的randint
步骤:
1.确定噪声添加位置
2.确定噪声种类
3.修改图像的灰度值
4.得到图像
点击查看代码
import cv2 as cv
import numpy as np
import sys
def add_noisy(image, n=10000):
ret = image.copy()
w, h = image.shape[:2]
for i in range(n):
# 噪声产生位置
x = np.random.randint(1, w)
y = np.random.randint(1, h)
if np.random.randint(0, 2) == 0:
# 产生白色颗粒
res[x, y] = 255
else:
res[x, y] = 0
return ret
if __name__ == '__main__':
img = cv.imread('../preview.jpg')
if img is None:
print('import img error')
sys.exit()
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
res = add_noisy(img)
cv.imshow('noisy_img', res)
cv.waitKey(0)
cv.destroyAllWindows()

高斯噪声:
指噪声分布符合高斯分布及正态分布 主要产生原因由于拍摄时的场地较暗且亮度不均匀,高斯噪声出现在
图像中的全部位置
同样可以使用numpy来模拟高斯噪声
np.random.normal(loc,scale,size)
loc: 高斯分布的平均值
scale: 标准差
'''
def add_gauss_noisy(img, mean=0, val=0.01):
size = img.shape
img = img / 255
gauss = np.random.normal(mean, val, size)
noise = img + gauss
return noise
'''

区别不是很大
滤波算法
滤波是为了去除图像中不重要的内容 使图像更加清晰 例如: 去除图像中的噪音 提取某些信息等
根据滤波目的 图像滤波分为了 : 消除图像噪音的滤波 和 提取图像中关键数据的滤波
图像滤波的要求 : 1.不能破坏图像的轮廓和边缘信息 2.图像处理过后更加清晰图像滤波使用的滤波器决定了滤波操作的作用:
噪声信号集中在高频 所以 使用滤波器允许低频和中频可以去除图像中的噪音
对于纹理变化的区域 信号频率很高 使用高通滤波器 可以达到锐化边缘的目的图像滤波分为线性滤波和非线性滤波
线性滤波
线性滤波常用的有 均值滤波 方框滤波 高斯滤波 图像的线性滤波和图像的卷积有相似的地方
均值滤波:
ret = cv.blur(src,ksize)
ksize: 给出大小,自动给出卷积核
特点: 滤波器越大 返还图像越模糊
'''
def mean_wash(img, ksize):
img = cv.blur(img, ksize)
return img
'''
方框滤波:
均值滤波的一般形式 只是不将元素值进行平均 而是直接用其和
ret = cv.boxFilter(src,ddepth,ksize)
高斯滤波:
因为现实情况中很容易引入高斯噪声 所以对针对高斯噪声的滤波是必要的
cv.GaussianBlur(src,ksize,sigmaX,sigmaY)
sigmaX: 在x轴上的标准偏差
sigmaY: 在y轴上的标准偏差
该函数可以根据输入的参数自动生成滤波器
ksize可以不是正方形 并且可以为0 为0可以自动计算出大小
当sigmaX和sigmaY 都为0的时候 表示根据滤波器的大小计算两个方向上的标准差数值
为了得到明确的结果
一般会确定 ksize sigmaX sigmaY 的值

利用高斯滤波处理椒盐噪音和高斯噪音
非线性滤波
非线性滤波的结果不是滤波器内的像素值进行线性组合得到的,其计算过程可能包含了排序 逻辑运算等等
因为线性滤波是所有像素值的线性组合 所以 噪音也会被包含进去,噪音只是更柔性 而非消失
常见的非线性滤波有: 中值滤波 双边滤波
中值滤波:
中值滤波是使用滤波器内的所有像素的中值来代替滤波器中心位置的像素值 是一种基于排序统计理论的能够
有效抑制噪音的非线性信号处理方法 , 不用想就知道肯定对椒盐噪音的处理效果很好
res = cv.medianBlur(src,ksize)
ksize: 不是给出一个() 而是一个 大于1的奇数

利用中值滤波处理椒盐噪音 效果very good
双边滤波:
一种经典的可以保留图片边缘信息的滤波算法
双边滤波是一种综合考虑滤波器内空域信息和图像灰度的相似度的滤波算法
可以在保留信息的基础上去除噪声。
img = cv.bilateralFilter(src,d,sigmaColor,sigmaSpace)
d: 滤波器的直径 当大于5时 函数会变慢 d越大 越糊
第三个参数越大 像素邻域的越多颜色会被混到一起 越大越糊
第四个参数越大 越远的像素点会相会影响
第三第四个参数大于150后会有较明显效果 小于10时效果很小

据说有美颜效果
代码汇总:
点击查看代码
import cv2 as cv
import numpy as np
import sys
def double_wash(img, d=5, sigColor=50, sigSpace=50):
img = img.copy()
img = cv.bilateralFilter(img, d, sigColor, sigSpace)
return img
def median_wash(img, ksize):
img = img.copy()
img = cv.medianBlur(img, ksize)
return img
def gauss_wash(img, ksize=(3, 3), sigX=10, sigY=20):
img = img.copy()
img = cv.GaussianBlur(img, ksize, sigX, sigY)
return img
def mean_wash(img, ksize):
img = img.copy()
img = cv.blur(img, ksize)
return img
def box_wash(img, ksize):
img = img.copy()
img = cv.boxFilter(img, -1, ksize, normalize=False)
return img
def add_gauss_noisy(img, mean=0, val=0.01):
size = img.shape
img = img / 255
gauss = np.random.normal(mean, val, size)
noise = img + gauss
return noise
def add_noisy(image, n=10000):
ret = image.copy()
w, h = image.shape[:2]
for i in range(n):
# 噪声产生位置
x = np.random.randint(1, w)
y = np.random.randint(1, h)
if np.random.randint(0, 2) == 0:
# 产生白色颗粒
ret[x, y] = 255
else:
ret[x, y] = 0
return ret
if __name__ == '__main__':
img = cv.imread('../preview.jpg')
img2 = cv.imread('../img_test.jpg')
if img is None:
print('import img error')
sys.exit()
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# cv.imshow('old', img)
res1 = add_noisy(img)
res2 = add_gauss_noisy(img)
# cv.imshow('noisy', res1)
# cv.imshow('gauss', res2)
res1_wash = gauss_wash(res1, (7, 7))
res2_wash = gauss_wash(res2, (5, 5))
median_res = median_wash(res1, 3)
double_res = double_wash(img2, 5, 200, 200)
# cv.imshow('wash1', res1_wash)
# cv.imshow('wash2', res2_wash)
# cv.imshow('wash3', median_res)
cv.imshow('old',img2)
cv.imshow('wash4', double_res)
cv.waitKey(0)
cv.destroyAllWindows()

浙公网安备 33010602011771号