(学习笔记)图像滤波及其python实现

1.图像滤波

图像滤波是在尽量保留原图像细节特征的条件下,对该图像的噪声进行抑制,处理效果的好坏会直接影响后续操作的有效性。
消除图像中噪声数据的过程叫做图像滤波或图像平滑,图像中的有效信息主要集中在低频和中频区域,高频区域中的有效信息会被噪声数据影响。
图像滤波的目的: 消除图像中的噪声;为图像识别等后续操作提取中相应的特征。
图像滤波的要求: 尽可能地不破坏原图像中的特征(如边缘);视觉效果应更好。
(1)均值滤波
均值滤波是一种低通滤波器,高频信号将会被去掉,可消除图像中尖锐噪声,其思想是利用某一个像素点和它周围8邻域的像素值构建成一个算子,计算它们的均值,并用均值替换原图像该点的像素值。
(2)中值滤波
中值滤波是消除图像噪声较为常用的方法,处理椒盐噪声效果较好,其思想是利用某一个像素点和它周围8邻域的像素值构成一个算子,将它们排序后,并用中间的值替换原图像该点的像素值。
(3)最大最小值滤波
最大最小值滤波的思想是利用某一个像素点和它周围8邻域的像素值构成一个算子,将他们排序后,若中值比最大值大,将原图像该点像素值替换为该算子中的最大值,反之,替换为最小值,若处于最大值和最小值之间,可指定原图像该点的像素值为最大值/最小值。
(4)sobel算子
sobel算子是一个矩阵,主要用于图像中物体的边缘提取。在这里插入图片描述
(5)高斯平滑
高斯平滑呈高斯分布,突出了中心点在像素平滑后的权重,有着较好的滤波效果,二维高斯公式如下:
在这里插入图片描述
(6)线性滤波
线性滤波的处理操作是利用权重矩阵(算子)与图像中某几个点对应相乘,并进行求和操作。(具体的讲解可参考下图的转载链接)
在这里插入图片描述
(图像转自https://blog.csdn.net/zouxy09/article/details/49080029,侵删)

2.各个方法实现步骤

(1)均值滤波
a.对原图像进行填充操作(padding)
b.取原图像的9个点作为kernel
c.求均值
d.更新像素值
e.直到循环结束
f.返回新图像
(2)中值滤波
a.对原图像进行填充操作(padding)
b.计算中位数位置
c.选取原图像的9个点作为kernel
d.排序
e.选取中间值更新原图像像素值
f.直到循环结束
g.返回新图像
(最大最小值滤波与中值滤波相似,此处不在重复说明)
(3)sobel算子
a.生成sobel矩阵
b.返回sobel矩阵
(4)高斯平滑
a.根据高斯公式计算高斯算子(其中x,y的计算方法可见https://blog.csdn.net/shawroad88/article/details/87935922)
b.进行线性滤波操作
(对高斯平滑加深理解可见https://www.zhihu.com/question/54918332)
(5)线性滤波
a.对原图像进行填充操作(padding)
b.截取图像中n*n个像素点与权重矩阵对应相乘
c.求和
d.更新像素值
e.对图像进行阶段操作(像素值大于255,令它为255,小于0,对该点像素进行abs操作)
f.直到循环结束
g.返回新图像

3.python实现

(1)均值滤波

def mean_filter(src,kernel_size,epoch):#均值滤波
    kernel_height,kernel_weight=kernel_size
    dst=src
    pad_num=int(np.floor(kernel_weight/2))#计算需要加的边
    pad_src=np.pad(src,((pad_num,pad_num),(pad_num,pad_num)),'constant')#加边
    for z in range(epoch):#迭代
        for i in range(pad_num,pad_src.shape[0]-pad_num):#滤波
            for j in range(pad_num,pad_src.shape[1]-pad_num):
                sum_temp=sum(pad_src[i-pad_num:i+pad_num+1,j-pad_num:j+pad_num+1]).tolist()#求和
                #print(sum_temp)
                sum_temp=sum(sum_temp)
                #print(sum_temp)
                temp=sum_temp/(kernel_weight*kernel_height)#求均值
                dst[i-pad_num,j-pad_num]=temp#更新像素
        src=dst#更新原图像
        pad_src = np.pad(src, ((pad_num, pad_num), (pad_num, pad_num)), 'constant')
    dst = dst.astype(np.uint8)
    return dst

(2)中值滤波

def median_filter(src,kernel_size,epoch):#中值滤波
    kernel_height,kernel_weight=kernel_size
    pad_num=int(np.floor(kernel_height/2))#计算需要添加的边
    center=int(np.round((kernel_height*kernel_weight)/2))#计算中位数
    dst=src
    pad_src=np.pad(src,((pad_num,pad_num),(pad_num,pad_num)),'constant')#加边
    for z in range(epoch):#迭代
        for i in range(pad_num, src.shape[0] - pad_num):#滤波
            for j in range(pad_num, src.shape[1] - pad_num):
                temp = pad_src[i - pad_num:i + pad_num + 1, j - pad_num:j + pad_num + 1].flatten().tolist()#获取n*n的矩阵并平展
                temp = sorted(temp)#排序
                dst[i - pad_num, j - pad_num] = temp[center]#更新像素值
        src=dst#更新原图像
        pad_src = np.pad(src, ((pad_num, pad_num), (pad_num, pad_num)), 'constant')
    dst=dst.astype(np.uint8)
    return dst

(3)sobel算子

def sobel_kernel():
    sobel_horizontal=np.array([[1,2,1],[0,0,0],[-1,-2,-1]]).astype(np.uint8)#水平sobel算子
    sobel_vertical=sobel_horizontal.T#垂直sobel算子
    return sobel_horizontal,sobel_vertical

(4)高斯平滑

def guass_kernel(kernel_size,sigma):#创建高斯kernel
    kernel_height,kernel_weight=kernel_size
    kernel=np.zeros(kernel_size)#创建高斯kernel
    for i in range(kernel_height):
        for j in range(kernel_weight):
            r=math.pow((i-(kernel_height-1)/2),2)#计算x
            c=math.pow((j-(kernel_weight-1)/2),2)#计算y
            kernel[i,j]=(1/(2*math.pi*math.pow(sigma,2)))*math.exp(-(math.pow(r,2)+math.pow(c,2))/(2*math.pow(sigma,2)))#按照高斯公式计算每一个kernel的值
    sum_temp=sum(kernel)#求和
    kernel=kernel/sum_temp#最终的高斯kernel
    return kernel

(5)线性滤波

def sliding_window(src,kernel,stride):#用于单通道滑窗
    dst = src
    kernel_height,kernel_weight=kernel.shape#获取kernel的高度和宽度
    exnum=int(np.floor(kernel_height/2))#填充的维数,floor函数向下取整
    img_pad=np.pad(src,((exnum,exnum),(exnum,exnum)),'constant')#给图像加边,方便滑窗
    for i in range(exnum,img_pad.shape[0]-exnum,stride):
        for j in range(exnum,img_pad.shape[1]-exnum,stride):
            temp=(img_pad[i-exnum:i+exnum+1,j-exnum:j+exnum+1]*kernel)/(kernel_height*kernel_weight)#截取n*n的mat与kenel对应相乘
            sum_temp=sum(temp).tolist()#相加
            sum_temp=sum(sum_temp)
            img_pad[i,j]=sum_temp#更新像素
            if img_pad[i,j]<0:#截断操作
                img_pad[i,j]=abs(img_pad[i,j])
            if img_pad[i,j]>255:
                img_pad[i,j]=255
            dst[i-exnum,j-exnum]=img_pad[i,j]
    dst=dst.astype(np.uint8)
    return dst

(6)测试代码

#均值滤波
img=cv2.imread("1.png",0)
dst=mean_filter(img,(3,3),5)
print(dst)
cv2.imshow("dst",dst)
cv2.waitKey(0)
#中值滤波
img=cv2.imread("1.png",0)
dst=mean_filter(img,(3,3),5)
print(dst)
cv2.imshow("dst",dst)
cv2.waitKey(0)
#高斯滤波
kernel=guass_kernel((3,3),1.5)
print(kernel)
img=cv2.imread("1.png",0)
dst=sliding_window(img,kernel,1)
cv2.imshow("dst",dst)
cv2.waitKey(0)
#sobel
sobel_kernel_horizontal,sobel_kernel_vertical=sobel_kernel()
img=cv2.imread("1.png",0)
dst_horizontal=sliding_window(img,sobel_kernel_horizontal,1)
dst_vertical=sliding_window(img,sobel_kernel_vertical,1)
dst=dst_horizontal+dst_vertical
cv2.imshow("dst_horizontal",dst_horizontal)
cv2.imshow("dst_vertical",dst_vertical)
cv2.imshow("dst",dst)
cv2.waitKey(0)

4.总结

(1)均值滤波
优点:算法简单,计算速度较快。
缺点:降噪的同时会使得图像模糊,尤其是物体的边缘。
(2)中值滤波
优点:抑制噪声效果较好,图像的清晰度基本保持。
缺点:对高斯噪声的抑制效果不是很好。
(3)sobel
主要用于提取物体的边缘。

  • 0
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值