九 模糊操作-程序员宅基地

 

推文 https://blog.csdn.net/xw20084898/article/details/21822565

推文 https://blog.csdn.net/on2way/article/details/46828567

三种模糊操作

均值模糊

中值模糊

自定义模糊(可以实现上面两种模糊方式)

 

这个算法类似有:均值,中值,就是取周围所有像素的均值、中值来设置这个像素的大小。

 

(关于边界问题:有几种填充方法:补零、边界复制、块复制、镜像复制等方法)

原理

图像处理:基础(模板、卷积运算)

 

图像处理-模板、卷积的整理

基于离散卷积

定义好每个卷积核

不同卷积核得到不同的卷积效果

模糊是卷积的一种表象

 一、均值模糊blur

opencv有一个专门的平均滤波模板供使用–归一化卷积模板,所有的滤波模板都是使卷积框覆盖区域所有像素点与模板相乘后得到的值作为中心像素的值。
Opencv中均值模板可以用cv2.blur和cv2.boxFilter,比如一个3*3的模板其实就可以如下表示:

模板大小是m*n是可以设置的。如果你不想要前面的1/9,可以使用非归一化的模板cv2.boxFilter。

1 img = cv.imread('11.jpg')
2 img1 = cv.blur(img,(10,10))
3 cv.imshow('img',img)
4 cv.imshow('img1',img1)
5 cv.waitKey(0)
6 cv.destroyAllWindows()

均值模糊函数blur():

定义:blur(src,ksize,dst=None, anchor=None, borderType=None)

定义是有5个参数,但最后三个均为none,所以也就2个参数

src:要处理的原图像

ksize: 必须是奇数卷积核,周围关联的像素的范围:代码中(5,5)就是5*5的大小,就是计算这些范围内的均值来确定中心位置的大小

二、中值模糊mediablur

中值滤波模板就是用卷积框中像素的中值代替中心值,达到去噪声的目的。 这个模板一般用于去除椒盐噪声。 前面的滤波器都是用计算得到的一个新值来取代中心像素的值,而中值滤波是用中心像素周围(也可以使他本身)的值来取代他,卷积核的大小也是个奇数。

 1 img = cv.imread('11.jpg')
 2 gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
 3 cv.imshow('gray',gray)
 4 for i in range(2000):
 5     x = np.random.randint(0,gray.shape[0])
 6     y = np.random.randint(0,gray.shape[1])
 7     gray[x,y] = 255
 8 cv.imshow('new_gray',gray)
 9 dst = cv.medianBlur(gray,9) #注意,中值模糊的ksize一个数字就可以了,这里是9*9
10 cv.imshow('dst',dst)
11 cv.waitKey(0)
12 cv.destroyAllWindows()

中值模糊函数medianBlur(): 

定义:medianBlur(src, ksize, dst=None)

ksize与blur()函数不同,不是矩阵,而是一个数字,例如为5,就表示了5*5的方阵

可以看到中值滤波对于这些白点噪声的去除是非常的好的。

 三、高斯模糊GaussianBlur

1、原理

2、原理代码

def clamp(pv):  #使我们的随机值在0-255之间
    if pv > 255:
        return 255
    elif pv < 0:
        return 0
    else:
        return pv

import cv2 as cv
import numpy as np

def gaussian_noise(image):  #对图像加上高斯噪声
    h,w,c = image.shape
    for row in range(h):  #十分耗时
        for col in range(w):
            s = np.random.normal(0,20,3)  #产生3个随机值,符合正态分布,第一个参数是概率分布的均值,对应分布中心,,第二个是概率分布的标准差,越小越瘦高,第三个是输出的值个数
            b = image[row,col,0] #blue
            g = image[row,col,1] #green
            r = image[row,col,2] #red
            image[row,col,0] = clamp(b+s[0])  #为什么像素值是整数的怎么会和float相加呢?
            image[row,col,1] = clamp(g+s[1])
            image[row,col,2] = clamp(r+s[2])

    cv.imshow("noise image",image)


src = cv.imread("./1.png")  #读取图片
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)    #创建GUI窗口,形式为自适应
cv.imshow("input image",src)    #通过名字将图像
gaussian_noise(src)

cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv.destroyAllWindows()  #销毁所有窗口

 推文:从np.random.normal()到正态分布的拟合

3、使用opencv高斯模糊

高斯平滑函数GaussianBlur()

定义:GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)

src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
ksize,高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数(并不能理解)。或者,它们可以是零的,它们都是由sigma计算而来。
sigmaX,表示高斯核函数在X方向的的标准偏差。  根据这个可以获取sigmaY,若是sigmaX和sigmaY都没有则根据ksize获取
sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
为了结果的正确性着想,最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。
borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。

1 img = cv.imread('11.jpg')
2 gaosi = cv.GaussianBlur(img,(0,0),15)  #(0,0),然后根据sigmaX=15自动计算ksize
3 cv.imshow('img',img)
4 cv.imshow('gaosi',gaosi)
5 cv.waitKey(0)
6 cv.destroyAllWindows()

 

4、对高斯噪声图进行高斯模糊(发现高斯噪声的影响不大,高斯模糊对其有抑制作用)

img = cv.imread('11.jpg')
cv.imshow('image',img)
gaosi_noise(img)
gaosi = cv.GaussianBlur(img,(0,0),10)
cv.imshow('gaosi',gaosi)
cv.waitKey(0)
cv.destroyAllWindows()

四、边缘保留滤波EPF

OpenCV经典的两种实现EPF方法:高斯双边和均值迁移

1、双边模糊

只模糊上半部分,下半部分差异太大,没有模糊

 差异越大,越会完整保留

双边滤波函数bilateralFilter():

定义:bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)

值域和空域的两个方差sigma可以简单的设置为相等,小于10,无太大效果,大于150效果太强,像卡通片似的。
滤波器尺寸d:大于5将较慢(5 forreal-time),d=9,for off-lineapplications,d 是像素邻域“直径”。计算的半径,半径之内的像数都会被纳入计算,如果提供-1或者0,会从后面的参数sigmaSpace中自动计算。
Sigma_color(颜色标准差):颜色空间过滤器的sigma值,这个参数的值越大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
Sigma_space(空间标准差):坐标空间中滤波器的sigma值,如果该值较大,则意味着颜色相近的较远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace五官,否则d正比于sigmaSpace.

双边滤波的内在想法是:在图像的值域(range)上做传统滤波器在空域(domain)上做的工作。空域滤波对空间上邻近的点进行加权平均,加权系数随着距离的增加而减少;值域滤波则是对像素值相近的点进行加权平均,加权系数随着值差的增大而减少。

 

 想要得到比较好的结果,3/4/5参数最好都指定。d>5那么计算会很慢,所以一般都设置为d=5,如果少数情况需要去除比较大的噪声,那么d=9,要去的较好的平滑效果,最好在9附近。

d或者sigma_space设置的越大,包含的范围越大,耗时越长

 1 def bi_demo(image):
 2     dst = cv.bilateralFilter(image,0,100,15)  #第二个参数d是distinct,我们若是输入了d,会根据其去算第3或4个参数,我们最好是使用第3或4个参数反算d,先设为0
 3     cv.imshow("dst",dst)
 4 
 5 src = cv.imread("1.jpg")  #读取图片
 6 cv.namedWindow("img",cv.WINDOW_AUTOSIZE)    #创建GUI窗口,形式为自适应
 7 cv.imshow("img",src)    #通过名字将图像和窗口联系
 8 bi_demo(src)
 9 cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
10 cv.destroyAllWindows()  #销毁所有窗口

若是高斯模糊,则整体都会模糊掉,实现滤镜效果。

2、均值迁移

推文:Opencv均值漂移pyrMeanShiftFiltering彩色图像分割流程剖析

meanShfit均值漂移算法是一种通用的聚类算法,它的基本原理是:对于给定的一定数量样本,任选其中一个样本,以该样本为中心点划定一个圆形区域,求取该圆形区域内样本的质心,即密度最大处的点,再以该点为中心继续执行上述迭代过程,直至最终收敛。

可以利用均值偏移算法的这个特性,实现彩色图像分割,Opencv中对应的函数是pyrMeanShiftFiltering。这个函数严格来说并不是图像的分割,而是图像在色彩层面的平滑滤波,它可以中和色彩分布相近的颜色,平滑色彩细节,侵蚀掉面积较小的颜色区域,所以在Opencv中它的后缀是滤波“Filter”,而不是分割“segment”。先列一下这个函数,再说一下它“分割”彩色图像的实现过程。

pyrMeanShiftFiltering(src, sp, sr, dst=None, maxLevel=None, termcrit=None): 

第一个参数src,输入图像,8位,三通道的彩色图像,并不要求必须是RGB格式,HSV、YUV等Opencv中的彩色图像格式均可;

第二个参数sp,定义的漂移物理空间半径大小;  #越大,细节丢失越多

第三个参数sr,定义的漂移色彩空间半径大小;

第四个参数dst,输出图像,跟输入src有同样的大小和数据格式;

第五个参数maxLevel,定义金字塔的最大层数;

第六个参数termcrit,定义的漂移迭代终止条件,可以设置为迭代次数满足终止,迭代目标与中心点偏差满足终止,或者两者的结合;

dst = cv.pyrMeanShiftFiltering(image,10,50)   #一般这三个参数就可以了

五、自定义模糊fileter 2D

推文:图像滤波函数imfilter函数的应用及其扩展

Opencv提供的一个通用的2D滤波函数为cv2.filter2D(),
滤波函数的使用需要一个核模板,对图像的滤波操作过程为:将和模板放在图像的一个像素A上,求与之对应的图像上的每个像素点的和,
核不同,得到的结果不同,而滤波的使用核心也是对于这个核模板的使用,需要注意的是,该滤波函数是单通道运算的,
也就是说对于彩色图像的滤波,需要将彩色图像的各个通道提取出来,对各个通道分别滤波才行。

filter2D(src,ddepth,kernel):

ddepth:深度,输入值为-1时,目标图像和原图像深度保持一致

kernel: 卷积核(或者是相关核),一个单通道浮点型矩阵

 1、实现中值模糊

1 img = cv.imread('1.jpg')
2 cv.imshow('img',img)
3 gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
4 cv.imshow('gray',gray)
5 kernel = np.ones([5,5],np.float32)/25  
6 dst = cv.filter2D(gray,-1,kernel) 7 cv.imshow('dst',dst) 8 cv.waitKey(0) 9 cv.destroyAllWindows()

声明二维数组5*5,初始化1,保证值不溢出,除以数组大小,实现中值模糊,自定义卷积核的算子

上述生成的5*5核模板其实就是一个均值滤波。,当我们是/25就是中值滤波,归一化处理

 

2、实现锐化处理

使用的kernel是:,实现锐化处理,提高图像的对比度,提高立体感,轮廓更加清晰。

img = cv.imread('1.jpg')
cv.imshow('img',img)
kernel = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]],np.float32)
dst = cv.filter2D(img,-1,kernel)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

 

 

转载于:https://www.cnblogs.com/pacino12134/p/9856995.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/apbckk1506/article/details/101830587

智能推荐

react进阶之异常处理机制-error Boundaries_react-error-boundaries-程序员宅基地

该文章翻译自官网 https://reactjs.org/docs/error-boundaries.html在过去,JS在组件内的错误通常会污染React的内部state并且造成它发出一个让人难以理解的错误给下一个render,通常我们在浏览器控制台看到的错误往往是上一个程序代码里面一个更早的错误引起的,但是React并没有提供一个方式在组件中优雅的解决他们,并且不能从恢复这些错误。Er_react-error-boundaries

解决在IE9,IE10浏览器下,程序没有任何错误,easy ui页面不加载任何数据的问题...-程序员宅基地

对于web应用程序,经常用到开发人员工具,按F12,可以调试脚本,可以查看监视网络,查看各页面加载时间,非常方便,今天在调试js时,不小心打开了兼容性视图,之后每次打打开页面时,均不显示页面post回传数据,找了半天,终于找出原因了,在这里记录一下,取消兼容性视图后,页面数据显示正常。打开兼容视图后显示的页面:关闭兼容视图后显示转载于:https://www...._easy ui ie 9

关于TCP/IP,HTTP,Socket的那些事_ios socket面试-程序员宅基地

SocketSocket是应⽤层与TCP/IP协议族通信的中间软件抽象层,它是一组接⼝。在设计模式中,Socket其实就是一个⻔面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对⽤户来说,⼀组简单的接⼝就是全部,让 Socket去组织数据,以符合指定的协议。先从服务器端说起1>服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accep_ios socket面试

Qt实用技巧:设计模式之单例模式,唯一实例类通用模板_qt单例加锁-程序员宅基地

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。_qt单例加锁

el-date-picker自定义选择时间&&el-time-select自定义选择时间实现避免时间冲突-程序员宅基地

element-ui el-data-time 自定义选择时间开始日期不能小于结束日期,两个选择框之间的互相限制_el-time-select

mysql/sqlserver修改整列的值/给整列添加一个前缀_sqlserver给数据加前缀-程序员宅基地

,问题描述:sqlserver中需要给主键id整列添加一个标识释:字符串拼接直接上代码sqlserver:update [dbo].[表名] set [列明] = concat(‘我爱java’,[列明]);这个执行后的效果就是,整列的值前缀变成:我爱java+原来的值如:id name5 ye6 chua7 jiang执行:update [dbo].[表名] set [id] = concat(‘我爱java’,[id]);数据就变成id _sqlserver给数据加前缀

随便推点

阿里面试被虐经历分享-程序员宅基地

说这次面试可真是揪心,太揪心了,14日晚上在合工大参加了笔试,之后就一直等着面试通知,可是16中午还没有通知,我实在是坐不住了,就去面试的酒店去看了看,问了一下,他们说通知还没有发完,实在没心情去等了,就跟他们说说,看看能不能直接去面试,正好有几个java面试官闲着,所以就安排我去面试了。面试的时间超过了一个小时,具体多少没注意。也问了很多很多问题,问的问题也很细很细,不过面试官也很有耐心。下面就...

HTML命名空间的使用_html中如何引入bin文件的命名空间-程序员宅基地

参考文章:http://msdn.microsoft.com/en-us/library/ms531076(v=vs.85).aspx1. 命名空间的注册... 2.使用在标签中可以使用这样的标签 3.如何获取(1) IEvar nam_html中如何引入bin文件的命名空间

r语言与统计分析考试题_R语言与统计分析[Statistical Analysis with R]pdf-程序员宅基地

R语言与统计分析[Statistical Analysis with R] 内容简介《R语言与统计分析/应用统计学丛书》以数据的常用统计分析方法为基础,在简明扼要地阐述统计学基本概念、基本思想与基本方法的基础上,讲述与之相对应的R函数的实现,并通过具体的例子说明统计问题求解的过程。《R语言与统计分析/应用统计学丛书》注重统计的思想性、方法的实用性和计算的可操作性。在内容的安排上不仅包含了基础统计分..._统计计算with r 答案

一道有趣的最短路 NEERC2017 Journey from Petersburg to Moscow-程序员宅基地

题目链接http://codeforces.com/gym/101630/attachments/download/6401/20172018-acmicpc-northeastern-european-regional-contest-neerc-17-en.pdf题意求111到nnn的最短路,最短路上只计算前kkk大的边。题解这道题的操作很骚,算法如下: 遍历每条边x...

linux 修改分区可读,linux怎样修改分区id 如何修改linux分区类型。 linux修改分区id 和修改linux分区类型的方法。...-程序员宅基地

今天给大家带来linux怎样修改分区id,如何修改linux分区类型。,linux修改分区id,和修改linux分区类型的方法。,让您轻松解决问题。 linux下LVM分区是学习linux必须掌握的一个内容,其中有关于lvm分区之前修改分区ID类型,把常见的83普通分区改成8e LVM标识。应该如何操作呢?具体方法如下:1输入fdisk/dev/dhbfdisk后面接上设备名称(IDE..._用hex为linux更改分区类型

windows上bug崩溃定位分析(Qt或者VS)_qt程序崩溃如何错误定位-程序员宅基地

任何情况下,都不能保证自己写的代码不会发生崩溃,崩溃不可怕,可怕的是无法定位哪里崩溃,特别是客户那边崩溃,开发者这边不崩溃,问题陷入僵局。自从有了下面这个神奇的代码,再也不怕了。以下代码亲自测试没问题。1. 如果是在VC++中,那么只需要将下列2个文件直接添加到工程中.发布程序后,如果发生了崩溃,那么在崩溃的文件中就已经记录了“哪个文件的哪一行发生了崩溃”。再也不用像以前那样要在项目属性中配置,要生成.map、.cod等等文件,然后计算偏移地址来分析了。2. 如果是在Qt+MinG._qt程序崩溃如何错误定位