图片操作笔记-滤波-python

滤波的应用

高斯噪声和椒盐噪声 两者在视觉上的区别就是,高斯噪声是和原来图像像素值相关的噪声,而椒盐噪声则是很多的黑白像素点
高斯噪声是一种加性噪声,即噪声直接加到原图像上,因此可以用线性滤波器滤除
椒盐噪声又称为脉冲噪声,它是一种随机出现的白点(盐噪声)或者黑点(椒噪声),类似把椒盐撒在图像上,因此得名,如电视里的雪花噪声等。
椒盐噪声可以认为是一种逻辑噪声,用线性滤波器滤除的结果不好,一般采用中值滤波器滤波可以得到较好的结果

滤波操作

自适应中值滤波
高斯滤波
双边滤波
导向滤波

自适应中值滤波算法

图片没用部分的噪声

import cv2
import numpy as np
from matplotlib import pyplot as plt
 
 
# for gray image
# S_max mast be grather 3
def auto_median_filter(img, S_max):
    output = img.copy()
 
    def class_B(z_xy, z_med, z_max, z_min):
        if (z_min < z_xy) & (z_xy < z_max):
            return z_xy
        else:
		    #z_xy 是个噪声,消除它: 使用z_med替换
            return z_med
 
    S_ori = 3
	# cv2.copyMakeBorder() 函数是用来在图像周围添加边框的
	# 增加边框,兼容边界的像素点
	# 可以在开始的时候增加S_max厚度的边框,后面就不用动态增加了
	# S_ori // 2  取整
    copy = cv2.copyMakeBorder(img, *[S_ori // 2] * 4, borderType=cv2.BORDER_DEFAULT)  # 补零
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            def class_A(copy, S_ori=3):
                board = S_ori // 2
                z_med = np.median(copy[i:i + board, j:j + board])
                z_max = np.max(copy[i:i + board, j:j + board])
                z_min = np.min(copy[i:i + board, j:j + board])
 
                if (z_min < z_med) & (z_med < z_max):
				    # z_med 不是噪声
                    output[i, j] = class_B(copy[i, j], z_med, z_max, z_min)
                else:
                    # next_size = S_ori + 2
					# # z_med 是个噪声,增大滤波窗口,寻找下一个不是噪声的中值
                    next_size = cv2.copyMakeBorder(copy, *[1] * 4, borderType=cv2.BORDER_DEFAULT)  # 增尺寸
                    S_ori = S_ori + 2
                    if S_ori <= S_max:
					    # 
                        return class_A(next_size, S_ori)
                    else:
					    #到达最大窗口,没有找到“不是噪声的中值”,直接中值滤波
                        output[i, j] = z_med
            class_A(copy, 3)
    return output.astype(np.uint8)
 
def label_def(): # 定义坐标数字字体及大小
    plt.xticks(fontproperties='Times New Roman', size=8)
    plt.yticks(fontproperties='Times New Roman', size=8)
 
if __name__ == '__main__':
    img = cv2.imread('D://pictures//Fig0335(a)(ckt_board_saltpep_prob_pt05).tif', 0)
    img_median = cv2.medianBlur(img, 7)
    out = auto_median_filter(img, 7)
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.subplot(131), plt.imshow(img, "gray"), plt.title('椒盐噪声', fontsize='small'), label_def()
    plt.subplot(132), plt.imshow(img_median, "gray"), plt.title('中值滤波', fontsize='small'), label_def()
    plt.subplot(133), plt.imshow(out, "gray"), plt.title('自适应中值滤波', fontsize='small'), label_def()
    plt.show()

高斯滤波

opencv函数 cv2.GaussianBlur(img,(3,3),1.3) 实现高斯滤波
其中(3,3)为滤波器的大小;1.3为滤波器的标准差,如果标准差这个参数设置为0,则程序会根据滤波器大小自动计算得到标准差。
图片内容里面噪声

import cv2
img=cv2.imread('../001.jpg')
#(3, 3)表示高斯滤波器的长和宽都为3,1.3表示滤波器的标准差
out=cv2.GaussianBlur(img,(3,3),1.3)
cv2.imwrite('out.jpg',out)

双边滤波

双边滤波是一种非线性滤波方法,是结合了图像的邻近度和像素值相似度的一种折中,在滤除噪声的同时可以保留原图的边缘信息。整个双边滤波是由两个函数构成:一个函数是由空间距离决定的滤波器系数,另外一个诗由像素差值决定的滤波器系数。
保全图像中的边缘信息,能在保持边界清晰的情况下有效的去除噪音
https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
API形如:cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace)

#API形如:cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace)

import cv2
img = cv2.imread('11.png')
# 双边滤波 
# params:img,处理半径 d=-1则自动计算,sigmaColor(灰度差权重),sigmaSpace(邻域距离权重)
# 灰度差越大(边缘),权重越小
# 邻域距离越大,权重越小
img01 = cv2.bilateralFilter(img, 51, 10, 10)
cv2.imshow("bilateralFilter01", img01)

https://zhuanlan.zhihu.com/p/522225954?utm_id=0

导向滤波

介绍-百度 http://www.taodudu.cc/news/show-5704877.html?action=onClick
在滤波效果上,引导滤波和双边滤波差不多,然后在一些细节上,引导滤波较好(在PS的磨皮美白中,经过亲生实践,效果更好)。
引导滤波最大的优势:可以写出时间复杂度与窗口大小无关的算法,因此在使用大窗口处理图片时,其效率更高。

import argparse  # 导包
import cv2
import matplotlib.pyplot as plt
import skimage

#cv2.guidedFilter(guide, src, dst, radius, eps[, dDepth]) 
#guide: nparrayguided image (or array of images) with up to 3 channels,if it have more then 3 channels then only first 3 channels will be used.
#src: nparrayfiltering image with any numbers of channels.
#radius: intradius of Guided Filter.
#eps: floatregularization term of Guided Filter.{eps}^2 is similar to the sigma in the color space into bilateralFilter().
#dDepth: intoptional depth of the output image. 一般取-1

img=cv2.imread('../001.jpg')
guide=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY) #用灰度图作为引导
dst1=cv2.ximgproc.guidedFilter(guide=guide,src=img,radius=8,eps=50,dDepth=-1)
dst2=cv2.ximgproc.guidedFilter(guide=guide,src=img,radius=8,eps=200,dDepth=-1)
dst3=cv2.ximgproc.guidedFilter(guide=guide,src=img,radius=8,eps=500,dDepth=-1)

cv2.imshow("Img",img)  
cv2.imshow("dst1",dst1)
cv2.imshow("dst2",dst2)
cv2.imshow("dst3",dst3)

实践操作

上面讲述完了,上干活
环境配置-少走弯路

# 我用的Python3.8
# 安装 cv2 包
pip3 install opencv-python
# 安装 cv2.ximgproc包
# 注意 opencv-contrib-python 和 opencv-python 版本号必须一致,否则问题无穷,哭不出的那种
pip list | grep opencv       
#>> opencv-python             4.7.0.72  
pip3 install opencv-contrib-python==4.7.0.72 
# 检查一下
pip list | grep opencv
>> opencv-contrib-python     4.7.0.72            
>> opencv-python             4.7.0.72  

Note:

  1. 目前自适应中值滤波算法之能处理灰度图片,后续优化
  2. 导向滤波,使用灰度做引导,因此读取的时候要注意参数 “cv2.IMREAD_COLOR”
import cv2
import numpy as np
from matplotlib import pyplot as plt
 
 
# for gray image
# S_max mast be grather 3
# 此算法只支持 灰度图片的滤波
def auto_median_filter(img, S_max):
    output = img.copy()
 
    def class_B(z_xy, z_med, z_max, z_min):
        if (z_min < z_xy) & (z_xy < z_max):
            return z_xy
        else:
		    #z_xy 是个噪声,消除它: 使用z_med替换
            return z_med
 
    S_ori = 3
	# cv2.copyMakeBorder() 函数是用来在图像周围添加边框的
	# 增加边框,兼容边界的像素点
	# 可以在开始的时候增加S_max厚度的边框,后面就不用动态增加了
	# S_ori // 2  取整
    copy = cv2.copyMakeBorder(img, *[S_ori // 2] * 4, borderType=cv2.BORDER_DEFAULT)  # 补零
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            def class_A(copy, S_ori=3):
                board = S_ori // 2
                z_med = np.median(copy[i:i + board, j:j + board])
                z_max = np.max(copy[i:i + board, j:j + board])
                z_min = np.min(copy[i:i + board, j:j + board])
 
                if (z_min < z_med) & (z_med < z_max):
				    # z_med 不是噪声
                    output[i, j] = class_B(copy[i, j], z_med, z_max, z_min)
                else:
                    # next_size = S_ori + 2
					# # z_med 是个噪声,增大滤波窗口,寻找下一个不是噪声的中值
                    next_size = cv2.copyMakeBorder(copy, *[1] * 4, borderType=cv2.BORDER_DEFAULT)  # 增尺寸
                    S_ori = S_ori + 2
                    if S_ori <= S_max:
					    # 
                        return class_A(next_size, S_ori)
                    else:
					    #到达最大窗口,没有找到“不是噪声的中值”,直接中值滤波
                        output[i, j] = z_med
            class_A(copy, 3)
    return output.astype(np.uint8)
 
def label_def(): # 定义坐标数字字体及大小
    plt.xticks(fontproperties='Times New Roman', size=8)
    plt.yticks(fontproperties='Times New Roman', size=8)
 
if __name__ == '__main__':
    img = cv2.imread('./image_002.png',cv2.IMREAD_GRAYSCALE)
    img_median = cv2.medianBlur(img, 7)
    out = auto_median_filter(img, 7) 
	#这里的image 要求必须是单通道的(cv2.IMREAD_GRAYSCALE),否则会 出现异常: " Use a.any() or a.all() ",因为np.max执行完之后,返回值不是一个而是一组
	#因此auto_median_filter的入参中img 必须是灰度的
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.subplot(231), plt.imshow(img, "gray"), plt.title('椒盐噪声', fontsize='small'), label_def()
    plt.subplot(232), plt.imshow(img_median, "gray"), plt.title(' 中值滤波', fontsize='small'), label_def()
    plt.subplot(233), plt.imshow(out, "gray"), plt.title('中值滤波', fontsize='small'), label_def()
    # 高斯滤波
    img = cv2.imread('./image_002.png',cv2.IMREAD_COLOR) 
    img_gaosi=cv2.GaussianBlur(img,(3,3),1.3)
    plt.subplot(234), plt.imshow(img_gaosi, "gray"), plt.title('高斯滤波', fontsize='small'), label_def()

    #双边滤波
    img01 = cv2.bilateralFilter(img, 51, 10, 10)
    plt.subplot(235), plt.imshow(img01, "gray"), plt.title('双边滤波', fontsize='small'), label_def()

    #导向滤波
    img = cv2.imread('./image_002.png',cv2.IMREAD_COLOR) # 
    guide=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY) #用灰度图作为引导,这里要求img 是多通道读取(cv2.IMREAD_COLOR),否则报异常 " 'scn' is 1 "
    dst1=cv2.ximgproc.guidedFilter(guide=guide,src=img,radius=8,eps=50,dDepth=-1)
    plt.subplot(236), plt.imshow(dst1, "导向滤波"), plt.title('dao xiang', fontsize='small'), label_def()

    plt.show()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值