通过将图像与低通滤波器内核卷积来实现图像模糊。它有助于消除噪音。它实际上从图像中去除了高频内容(例如:噪声,边缘)。因此在此操作中边缘会有点模(嗯,有模糊技术,也不会模糊边缘)。 OpenCV主要提供四种模糊技术。

需要注意的是,图像模糊也叫图像平滑,它有助于降低噪声,但有噪声与模糊并不是等同的。

均值模糊

这是通过将图像与标准化的盒式过滤器( normalized box filter)进行卷积来完成的。它只取内核区域下所有像素的平均值并替换中心元素。这是由函数cv2.blur()或cv2.boxFilter()完成的。查看文档以获取有关内核的更多详细信息。我们应该指定内核的宽度和高度。 3x3标准化的盒式过滤器如下所示:

$$K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}$$

 Note: 如果您不想使用规范化的框过滤器,请使用cv2.boxFilter()。将参数normalize = False传递给函数。

使用5x5大小的内核检查下面的示例演示:

  1. import cv2
  2. import numpy as np
  3.  
  4. img = cv2.imread("./Pictures/girl.png")
  5.  
  6. blur2 = cv2.blur(img, (5,5))
  7.  
  8. htich = np.hstack((img,blur2))
  9. cv2.imwrite("./Pictures/mreger_img.png", htich)
  10. cv2.imshow("merged_img", htich)
  11. cv2.waitKey(0)
  12. cv2.destroyAllWindows()

效果:

中值模糊(中值滤波)

这里,函数cv2.medianBlur()取内核区域下所有像素的中值,并用该中值替换中心元素。这对图像中的椒盐噪声非常有效。有趣的是,在上述滤波器中,中心元素是新计算的值,其可以是图像中的像素值或新值。但在中值模糊中,中心元素总是被图像中的某个像素值所取代。它有效地降低了噪音。其内核大小应为正奇数

     例如,自己手动添加的椒盐噪声、模拟实现的中值滤波、库中的中值滤波。

  1. import cv2
  2. import numpy as np
  3.  
  4. def saltpepper(img,rate):
  5. m=int((img.shape[0]*img.shape[1])*rate)
  6. for a in range(m):
  7. i=int(np.random.random()*img.shape[1])
  8. j=int(np.random.random()*img.shape[0])
  9. if img.ndim==2:
  10. img[j,i]=255
  11. elif img.ndim==3:
  12. img[j,i,0]=255
  13. img[j,i,1]=255
  14. img[j,i,2]=255
  15. for b in range(m):
  16. i=int(np.random.random()*img.shape[1])
  17. j=int(np.random.random()*img.shape[0])
  18. if img.ndim==2:
  19. img[j,i]=0
  20. elif img.ndim==3:
  21. img[j,i,0]=0
  22. img[j,i,1]=0
  23. img[j,i,2]=0
  24. return img
  25.  
  26. def My_medianBlur(img, kernal):
  27. l = int((kernal-1) / 2)
  28. ret = img.copy()
  29. for i in range(0, img.shape[0]):
  30. for j in range(0, img.shape[1]):
  31. x_s = y_s = -l
  32. x_t = y_t = l
  33. if i <= l:
  34. x_s = i
  35. if j <= l:
  36. y_s = j
  37. if i >= img.shape[0] - l - 1:
  38. x_t = img.shape[0] - i - 1
  39. if j >= img.shape[1] - l - 1:
  40. y_t = img.shape[1] - j - 1
  41. part=[]
  42. for k1 in range(x_s, x_t + 1):
  43. for k2 in range(y_s, y_t + 1):
  44. part.append(img[i + k1][j + k2])
  45. part.sort() #排序以找到中间值
  46. length = len(part)
  47. mid = int(length / 2)
  48. ret[i][j] = part[mid]
  49. return ret
  50.  
  51. raw_img = cv2.imread('./Pictures/1.jpg', cv2.IMREAD_GRAYSCALE)
  52.  
  53. img = raw_img.copy()
  54. sp_img = saltpepper(img,0.02) #添加椒盐噪声,会改变原图像
  55.  
  56. img1 = My_medianBlur(sp_img, 5)
  57. img2 = cv2.medianBlur(sp_img, 5)
  58.  
  59. htich1 = np.hstack((raw_img, sp_img))
  60. htich2 = np.hstack((img1, img2))
  61. vtich = np.vstack((htich1, htich2)) #对比显示,左上为原图,右上为添加椒盐噪声,左下为自实现中值滤波,右下为库中的中值滤波
  62.  
  63. cv2.imshow('median_img',vtich)
  64. cv2.waitKey(0)
  65. cv2.destroyAllWindows()

效果:

高斯模糊

在此,使用高斯核代替箱式滤波器。它是通过函数cv2.GaussianBlur()完成的。我们应该指定内核的宽度和高度,它应该是正数和奇数。我们还应分别指定X和Y方向的标准偏差,sigmaX和sigmaY。如果仅指定了sigmaX,则sigmaY与sigmaX相同。如果两者都为零,则根据内核大小计算它们。高斯模糊在从图像中去除高斯噪声方面非常有效。

与均值模糊相比,只是把卷积模板中的值换一下,不是全1了,换成一组符合高斯分布的数值放在模板里面,比如这时中间的数值最大,往两边走越来越小,构造一个小的高斯包。

如果需要,可以使用函数cv2.getGaussianKernel()创建高斯内核。

函数原型:

  1. dst = cv.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType=BORDER_DEFAULT]]]
参数 描述
SRC 输入图像
DST 输出图像
ksize 高斯内核大小。[高度宽度]。高度和宽度应该是奇数,并且可以具有不同的值。如果ksize设置为[0 0],则从sigma值计算ksize。
sigmaX 沿X轴(水平方向)的内核标准偏差。
sigmaY 沿Y轴(垂直方向)的内核标准偏差。如果sigmaY = 0,则sigmaX取sigmaX值
borderType 在图像边界上应用内核时指定图像边界。可能的值有:cv.BORDER_CONSTANT cv.BORDER_REPLICATE cv.BORDER_REFLECT cv.BORDER_WRAP cv.BORDER_REFLECT_101 cv.BORDER_TRANSPARENT cv.BORDER_REFLECT101 cv.BORDER_DEFAULT cv.BORDER_ISOLATED

(其实上面两种也有同样的参数)

上面的代码可以修改为高斯模糊:

  1. blur2 = cv2.GaussianBlur(img,(5,5),cv2.BORDER_DEFAULT)

效果:

双边滤波

cv2.bilateralFilter()在降低噪音方面非常有效,同时保持边缘清晰。但与其他过滤器相比,操作速度较慢。我们已经看到高斯滤波器采用像素周围的邻域并找到其高斯加权平均值。该高斯滤波器仅是空间的函数,即,在滤波时考虑附近的像素。它没有考虑像素是否具有几乎相同的强度。它不考虑像素是否是边缘像素。所以它也模糊了边缘,我们不想这样做。

双边滤波器在空间中也采用高斯滤波器,但还有一个高斯滤波器,它是像素差的函数。空间的高斯函数确保仅考虑附近的像素用于模糊,而强度差的高斯函数确保仅具有与中心像素相似强度的那些像素被认为是模糊的。因此它保留了边缘,因为边缘处的像素将具有较大的强度变化。

具体的,图像中每个像素处的强度值被来自附近像素的强度值的加权平均值替换。该权重可以基于高斯分布。至关重要的是,权重不仅取决于欧几里德像素距离,还取决于辐射度差异。例如,范围差异,例如颜色强度,深度距离等。这通过系统地循环每个像素并相应地调整相邻像素的权重来保留锐边。

参数 描述
src 原图片
dst 目标图片,形状与原图片相同
d 过滤期间使用的每个像素邻域的直径。如果它是负数,则从sigmaSpace计算。
sigmaColor 在颜色空间进行过滤,参数的值越大意味着像素邻域内的更远的颜色(参见sigmaSpace)将混合在一起,从而产生更大的半等颜色区域。
sigmaSpace 在坐标空间进行过滤,较大的参数值意味着只要它们的颜色足够接近,更远的像素就会相互影响(参见sigmaColor)。当d> 0时,无论sigmaSpace如何,它都指定邻域大小。否则,d与sigmaSpace成比例。

将上面的代码修改为双边滤波,与高斯模糊进行对比:

  1. blur3 = cv2.bilateralFilter(img,20,75,75)

效果:

可见,保留了线条,但脸部明显已被模糊。

2D卷积

与一维信号一样,图像也可以使用各种低通滤波器(LPF),高通滤波器(HPF)等进行滤波.LPF有助于消除噪声,模糊图像等.HPF滤波器有助于查找边缘图片。

OpenCV提供了一个函数cv2.filter2D()来将自定义内核与图像进行卷积。

例如,为了简便仍使用平均值,我们将尝试对图像进行平均滤波。 5x5平均滤波器内核如下所示:

$$K = \frac{1}{25} \begin{bmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix}$$

操作是这样的:将此内核保持在像素上方,添加该内核下方的所有25个像素,取其平均值并用新的平均值替换中心像素。它继续对图像中的所有像素执行此操作。试试这段代码并检查结果:

  1. import cv2
  2. import numpy as np
  3.  
  4. img = cv2.imread("./Pictures/girl.png")
  5.  
  6. blur2 = cv2.blur(img,(5,5),cv2.BORDER_DEFAULT)
  7.  
  8. kernel = np.ones((5,5),np.float32)/25
  9. blur3 = cv2.filter2D(img,-1,kernel)
  10.  
  11. htich = np.hstack((img,blur2,blur3))
  12. cv2.imwrite("./Pictures/mreger_img.png", htich)
  13. cv2.imshow("merged_img", htich)
  14. cv2.waitKey(0)
  15. cv2.destroyAllWindows()

效果:

参考链接:

1、高斯模糊https://www.tutorialkart.com/opencv/python/opencv-python-gaussian-image-smoothing/

2、双边滤波http://opencvexamples.blogspot.com/2013/10/applying-bilateral-filter.html

3、官方文档https://docs.opencv.org/3.1.0/d4/d13/tutorial_py_filtering.html

4、cv2.filter2D示例https://www.programcreek.com/python/example/89373/cv2.filter2D

Python-OpenCV——Image Blurring(Image Smoothing)的更多相关文章

  1. 搭建基于python +opencv+Beautifulsoup+Neurolab机器学习平台

    搭建基于python +opencv+Beautifulsoup+Neurolab机器学习平台 By 子敬叔叔 最近在学习麦好的<机器学习实践指南案例应用解析第二版>,在安装学习环境的时候 ...

  2. .NET + OpenCV & Python + OpenCV 配置

    最近需要做一个图像识别的GUI应用,权衡了Opencv+ 1)QT,2)Python GUI,3).NET后选择了.NET... 本文给出C#+Opencv和Python+Opencv的相应参考,节省 ...

  3. RPi 2B python opencv camera demo example

    /************************************************************************************** * RPi 2B pyt ...

  4. Python+OpenCV图像处理(一)

    Python+OpenCV图像处理(一): 读取,写入和展示图片 调用摄像头拍照 调用摄像头录制视频 1. 读取.写入和展示图片 图像读入:cv2.imread() 使用函数cv2.imread() ...

  5. python opencv show图片,debug技巧

    debug的时候可以直接把图片画出来debug. imshow函数就是python opencv的展示图片的函数,第一个是你要起的图片名,第二个是图片本身.waitKey函数是用来展示图片多久的,默认 ...

  6. Python+OpenCV图像处理(一)——读取显示一张图片

    先在此处先声明,后面学习python+opencv图像处理时均参考这位博主的博文https://blog.csdn.net/u011321546/article/category/7495016/2? ...

  7. Python+opencv 图像拼接

    1.http://www.cnblogs.com/skyfsm/p/7411961.html ,给出了很好地拼接算法实现 2.由于不是Python的,所以简单做了一些翻译转成Python+opencv ...

  8. 【python+opencv】直线检测+圆检测

     Python+OpenCV图像处理—— 直线检测 直线检测理论知识: 1.霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进 ...

  9. python - opencv 的一些小技巧备忘

    python - opencv 的一些小技巧备忘 使用python-opencv来处理图像时,可以像matlab一样,将一幅图像看成一个矩阵,进行矢量操作,以加快代码运行速度. 下面记录几个常用的操作 ...

  10. ubuntu14.04 python + opencv 傻瓜式安装解决方案

    ubuntu14.04  python + opencv 傻瓜式安装解决方案 ubuntu下使python和opencv来做开发的话,总要花那么点时间来配置环境.我偶然间发现了一种傻瓜式安装办法希望快 ...

随机推荐

  1. EditText 设置可以输入的字符,过滤不符合接口要求的数据的方法

    1.设置EditText的android:digits 属性, 这种方式可以指出要支持的字符.比如要限制只能输入数字和字母,可以这样android:digits="1234567890ABC ...

  2. C++ - main()函数参数

    main()函数及其参数说明 main()函数主要形式: int main(void) int main(int argc, char *argv[]) = int main(int argc, ch ...

  3. 卸载/安装ubuntu系统教程

    卸载ubuntu 1.修复Mbr 1.下载软件MbrFix,地址:https://www.softpedia.com/get/System/Hard-Disk-Utils/MBRFix.shtml 2 ...

  4. php网页上一页下一页翻页

    这几天做项目因为数据太多,需要对信息进行上下翻页展示,就自己写了翻页的代码 大致功能就是页面只显示几条信息,按上一页.下一页切换内容,当显示第一页时上一页和首页选项不可选,当页面加载到最后一页时下一页 ...

  5. JS高级学习历程-16

    [正则表达式] 1()小括号使用 作用:① 提高表达式优先级关系 ② 提取子字符串内容 模式单元,每个小括号都算作一个模式单元内容,按照内容的下标可以给小括号计数. var  reg = /([0-9 ...

  6. 《SQL 进阶教程》case :用一条 SQL 语句进行不同条件的统计

    进行不同条件的统计是case表达式的著名用法之一 select name,sum(case when sex = 1 then population else 0 end) as cnt_m,sum( ...

  7. path不相等的子集,父级

    SELECT a.path,b.path from comm_department_temp a INNER JOIN comm_department_temp b on a.id=b.parent_ ...

  8. rand()函数的用法

    C++中rand() 函数的用法 1.rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数. 2.如果你要产生0~99这100个整数中的一个随机整数, ...

  9. NET Everywhere

    NET Everywhere 8月份已经发布了.NET Core 2.0, 大会Keynote 一开始花了大量的篇幅回顾.NET Core 2.0的发布,社区的参与度已经非常高.大会的主题是.NET ...

  10. Mybatis 查询一个对象包含多个子对象 (List 包含 List)

    功能:查询一个数据列表 且每个数据中包含各自的子数据集合 使用场景:1. 当需要查询多订单数据且同时订单数据中需要包含订单明细数据时 2. 当需要查询多评论数据且同时评论数据中需要包含评论回复数据时 ...