python opencv图像处理(七)

网友投稿 469 2022-08-27


python opencv图像处理(七)

图像平滑(滤波)处理

这里先介绍一下图像的一些问题 每一幅图像都包含某种程度的噪声,噪声可以理解为由一种或者多种原因造成的灰度值的随机变化,如由光子通量的随机性造成的噪声等等。

而图像平滑技术或者是图像滤波技术就是用来处理图像上的噪声,其中,能够具备边缘保持作用的图像平滑处理,成为了大家关注的重点。

本文会介绍 OpenCV 中提供的图像平滑的 4 个算法:

均值滤波方框滤波高斯滤波中值滤波

先给之前的小姐姐做一个噪声处理吧 代码如下:

import cv2 as cvimport numpy as np# 读取图片img = cv.imread("data.jpg", cv.IMREAD_UNCHANGED)rows, cols, chn = img.shape# 加噪声for i in range(5000): x = np.random.randint(0, rows) y = np.random.randint(0, cols) img[x, y, :] = 255cv.imshow("noise", img)# 图像保存cv.imwrite("maliao_noise.jpg", img)# 等待显示cv.waitKey()cv.destroyAllWindows()

在这里随机将一些像素值改问255,白色

2D图像卷积

在介绍滤波之前先简单介绍下 2D 图像卷积,图像卷积其实就是图像过滤。

图像过滤的时候可以使用各种低通滤波器( LPF ),高通滤波器( HPF )等对图像进行过滤。

低通滤波器( LPF )有助于消除噪声,但是会使图像模糊。

高通滤波器( HPF )有助于在图像中找到边缘。

OpenCV 为我们提供了一个函数 filter2D() 来将内核与图像进行卷积。

我们尝试对图像进行平均滤波, 5 x 5 平均滤波器内核如下:

我们保持这个内核在一个像素上,将所有低于这个内核的 25 个像素相加,取其平均值,然后用新的平均值替换中心像素。它将对图像中的所有像素继续此操作,完整的示例代码如下:

import numpy as npimport cv2 as cvfrom matplotlib import pyplot as plt# 读取图片img = cv.imread("data.jpg", cv.IMREAD_UNCHANGED)rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)kernel = np.ones((5,5),np.float32)/25dst = cv.filter2D(rgb_img, -1, kernel)titles = ['Source Image', 'filter2D Image']images = [rgb_img, dst]for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([])plt.show()

均值滤波

均值滤波是指任意一点的像素值,都是周围 N * M 个像素值的均值。

其实均值滤波和上面的那个图像卷积的示例,做了同样的事情,我只是用 filter2D() 这个方法手动完成了均值滤波,实际上 OpenCV 为我们提供了专门的均值滤波的方法,前面图像卷积没有看明白的同学,可以再一遍均值滤波,我尽量把这个事情整的明白的。

还是来画个图吧:

这个核我们可以自定义大小,比如 5 * 5 ,3 * 3 , 10 * 10 等等,具体定义多大完全看疗效。

OpenCV 为我提供了 blur() 方法用作实现均值滤波,原函数如下:

def blur(src, ksize, dst=None, anchor=None, borderType=None)

kSize:内核参数,其实就是图片进行卷积的时候相乘的那个矩阵,具体的卷积是如何算的,网上有很多,我这里就不介绍了,所得到的图像是模糊的,而且图像其实是按照原来的比例缺少了(原图像-内核参数+1)^2个单元格。anchor: Point 类型,即锚点,有默认值 Point(-1, -1) ,当坐标为负值,就表示取核的中心。borderType: Int 类型,用于推断图像外部像素的某种边界模式,有默认值 BORDER_DEFAULT 。

接下来是均值滤波的示例代码:

import cv2 as cvimport matplotlib.pyplot as plt# 读取图片img = cv.imread("data.jpg", cv.IMREAD_UNCHANGED)rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)# 均值滤波blur_img = cv.blur(rgb_img, (3, 3))# blur_img = cv.blur(img, (5, 5))# blur_img = cv.blur(img, (10, 10))# blur_img = cv.blur(img, (20, 20))titles = ['Source Image', 'Blur Image']images = [rgb_img, blur_img]for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([])plt.show()

方框滤波

方框滤波和均值滤波核基本一致,其中的区别是需不需要进行归一化处理。

什么是归一化处理等下再说,我们先看方框滤波的原函数:

def boxFilter(src, ddepth, ksize, dst=None, anchor=None, normalize=None, borderType=None)

src: 原始图像。ddepth: Int 类型,目标图像深度,通常用 -1 表示与原始图像一致。 kSize: 内核参数。dst:输出与 src 大小和类型相同的图像。anchor: Point 类型,即锚点,有默认值 Point(-1, -1) 。normalize: Int 类型,表示是否对目标图像进行归一化处理。

当 normalize 为 true 时,需要执行均值化处理。

当 normalize 为 false 时,不进行均值化处理,实际上是求周围各像素的和,很容易发生溢出,溢出时均为白色,对应像素值为 255 。

完整示例代码如下:

import cv2 as cvimport matplotlib.pyplot as plt# 读取图片img = cv.imread('data.jpg')source = cv.cvtColor(img, cv.COLOR_BGR2RGB)# 方框滤波result = cv.boxFilter(source, -1, (5, 5), normalize = 1)# 显示图形titles = ['Source Image', 'BoxFilter Image']images = [source, result]for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([])plt.show()

高斯滤波

为了克服简单局部平均法的弊端(图像模糊),目前已提出许多保持边缘、细节的局部平滑算法。它们的出发点都集中在如何选择邻域的大小、形状和方向、参数加平均及邻域各店的权重系数等。

在高斯滤波的方法中,实际上是把卷积核换成了高斯核,那么什么是高斯核呢?

简单来讲就是方框还是那个方框,原来每个方框里面的权是相等的,大家最后取平均,现在变成了高斯分布的,方框中心的那个权值最大,其余方框根据距离中心元素的距离递减,构成一个高斯小山包,这样取到的值就变成了加权平均。

def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)

sigmaX: 表示 X 方向方差。

这里需要注意的是 ksize 核大小,在高斯核当中,核 (N, N) 必须是奇数, X 方向方差主要控制权重。

完整的示例代码如下

import cv2 as cvimport matplotlib.pyplot as plt# 读取图片img = cv.imread('data.jpg')source = cv.cvtColor(img, cv.COLOR_BGR2RGB)# 方框滤波result = cv.GaussianBlur(source, (3, 3), 0)# 显示图形titles = ['Source Image', 'GaussianBlur Image']images = [source, result]for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([])plt.show()

中值滤波

在使用邻域平均法去噪的同时也使得边界变得模糊。

而中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。

中值滤波具体的做法是选一个含有奇数点的窗口 W ,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。

def medianBlur(src, ksize, dst=None)

示例代码如下:

import cv2 as cvimport matplotlib.pyplot as plt# 读取图片img = cv.imread('data.jpg')source = cv.cvtColor(img, cv.COLOR_BGR2RGB)# 方框滤波result = cv.medianBlur(source, 3)# 显示图形titles = ['Source Image', 'medianBlur Image']images = [source, result]for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([])plt.show()

可以明显看到,目前中值滤波是对原图像降噪后还原度最高的,常用的中值滤波的图形除了可以使用方框,还有十字形、圆形和环形,不同形状的窗口产生不同的滤波效果。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Boot整合邮箱发送邮件实例
下一篇:API文档是什么意思?API是什么?API文档是什么?API和API文档有什么区别?
相关文章

 发表评论

暂时没有评论,来抢沙发吧~