OpenCV python(五)图像预处理:【降噪处理】滤波、腐蚀膨胀等操作

一、滤波操作

滤波是图像预处理降噪环节不可缺少的一部分,其可在不影响原图像主要特征的情况下,去除大部分噪音,决定了后续的图像质量,极大降低了后续图像处理的复杂程度。
OpenCV python中常用的3种滤波操作为均值滤波、中值滤波、高斯滤波,其各自的函数如下:

cv2.blur(img, (x, x))				# 均值滤波
cv2.medianBlur(img, x)				# 中值滤波
cv2.GaussianBlur(img, (x, x), 0)	# 高斯滤波

在该篇文章中有详细的介绍和案例,包括个人对于滤波方法选择的理解,有需要可以小小的看一下:OpenCV python(四)图像预处理:二值化 && 滤波操作
效果如下:
在这里插入图片描述

二、腐蚀膨胀

如上图所示,当我们使用滤波操作对图像进行降噪后,我们仍然无法得到一张单纯的太阳的二值化图像,即图像中仍然存在有一些噪声点。接下来就是本篇文章的正文,通过腐蚀膨胀,我们将得到一张只有太阳的二值化图像。

1、腐蚀

腐蚀操作和滤波一样,首先要选择一个奇数卷积核,核里非0的点则为感兴趣的点,和滤波操作一样,将此核遍历整张图像。当感兴趣的点为0时,则把中心点置为0,否则保持原状。
cv2.erode函数为opencv-python提供的腐蚀函数,具体如下所示:

img_erode = cv2.erode(img_bin, (x, x), iterations=number)       # 腐蚀

img_bin为二值化图像,(x, x)为卷积核,因此x为奇数,number为次数,即连续腐蚀number次。(此处x为偶数,opencv也不会报错)

2、膨胀

同腐蚀操作一样,膨胀操作也需要选择一个奇数卷积核,核里非0的点则为感兴趣的点,将核遍历整张图像。然后和腐蚀操作相反,当感兴趣点为非0值时,则把中心点置为255,否则保持原状。
cv2.dilate函数为opencv-python提供的膨胀函数,具体如下所示:

img_dilate = cv2.dilate(img_bin, (x, x), iterations=number)     # 膨胀

img_bin为二值化图像,(x, x)为卷积核,因此x为奇数,number为次数,即连续膨胀number次。(此处x为偶数,opencv也不会报错)

3、案例

一、滤波操作程序中的高斯滤波得到的二值化图像为基础,对其进行腐蚀和膨胀操作。

(1)、腐蚀案例

具体程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape

        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t1, img_g_bin = cv2.threshold(img_g, 170, 255, cv2.THRESH_BINARY)  # 二值化
        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY)  # 二值化

        img_erode = cv2.erode(img_GaussianBlur_bin, (3, 3), iterations=5)       # 腐蚀

        cv2.imshow("img_g", img_g)  # 显示RGB图像
        cv2.imshow("img_g_bin", img_g_bin)  # 显示二值化图像
        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_erode", img_erode)      # 显示腐蚀后的图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述
如上图所示,我们可以看到除太阳以外的噪声点确实被去掉了,但是太阳也被腐蚀掉了5个大圈。要想解决这个问题,要先看下膨胀操作该如何实现。

(2)、膨胀案例

具体程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape

        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t1, img_g_bin = cv2.threshold(img_g, 170, 255, cv2.THRESH_BINARY)  # 二值化
        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY)  # 二值化

        img_dilate = cv2.dilate(img_GaussianBlur_bin, (3, 3), iterations=5)     # 膨胀

        cv2.imshow("img_g", img_g)  # 显示RGB图像
        cv2.imshow("img_g_bin", img_g_bin)  # 显示二值化图像
        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_dilate", img_dilate)      # 显示膨胀后的图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述
如上图所示,我们可以看到包括太阳、噪声点在内的光点都被膨胀了5大圈,很明显这并不是我们想要看到的效果,但是如果我们在腐蚀后再加入膨胀操作,那是不是就能让太阳恢复到原本的状态呢?

(3)、腐蚀膨胀案例

具体程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape

        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t1, img_g_bin = cv2.threshold(img_g, 170, 255, cv2.THRESH_BINARY)  # 二值化
        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY)  # 二值化

        img_erode = cv2.erode(img_GaussianBlur_bin, (3, 3), iterations=5)       # 腐蚀
        img_dilate = cv2.dilate(img_erode, (3, 3), iterations=5)     # 膨胀

        cv2.imshow("img_g", img_g)  # 显示RGB图像
        cv2.imshow("img_g_bin", img_g_bin)  # 显示二值化图像
        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_end", img_dilate)      # 显示腐蚀膨胀后的图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述
如上图所示,噪声点已经全部消失,而太阳也恢复了原本的特征,形状和最初的二值化后的图像没有太大的差异。从代码中可以看到,我们先使用了(3, 3)的卷积核对二值化图像进行了5次腐蚀操作,此时噪声点已经被腐蚀掉了,但是太阳也少了大半截,这时候我们再使用(3, 3)的卷积核对腐蚀后的图像进行5次膨胀操作,因之前噪声点已经被腐蚀掉,所以起到膨胀效果的只有太阳这一特征物体。最后得到的二值化图像则是太阳恢复了,噪声点也消失了。

三、开、闭运算

1、开运算

开运算其实就是上述的腐蚀膨胀操作,简单来说,开运算 = 先腐蚀后膨胀
以下为opencv-python提供的开运算函数(cv2.MORPH_OPEN):

img_open = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_OPEN, (x, x))		# 开运算

2、闭运算

与开运算相反,闭运算 = 先膨胀后腐蚀
以下为opencv-python提供的闭运算函数(cv2.MORPH_CLOSE):

img_close = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_CLOSE, (x, x))		# 闭运算

3、案例

(1)、开运算案例

具体程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape

        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t1, img_g_bin = cv2.threshold(img_g, 170, 255, cv2.THRESH_BINARY)  # 二值化
        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY)  # 二值化

        img_open = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_OPEN, (3, 3))		# 开运算

        cv2.imshow("img_g", img_g)  # 显示RGB图像
        cv2.imshow("img_g_bin", img_g_bin)  # 显示二值化图像
        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_open", img_open)      # 显示开运算后的图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述

(2)、闭运算案例

以之前的案例为基础,这次改变了二值化的模式,改为cv2.THRESH_BINARY_INV,即大于阈值的部分取0,小于等于阈值的部分取最大值。如何再进行闭运算可观察出闭运算的作用。
关于二值化的其他模式可在此篇文章中查到,这里就不再赘述了:OpenCV python(四)图像预处理:二值化 && 滤波操作
具体程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape
        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY_INV)  # 二值化

        img_close = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_CLOSE, (5, 5))  # 闭运算

        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_close", img_close)      # 显示闭运算后的图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述
可以看到,虽然不明显,但是确实是降噪了,道理还是差不多的,先膨胀将小黑洞膨胀掉,然后再腐蚀复原其他地方,这样子就能保证其他地方不变,同时实现降噪功能。如果是想要去掉另外两个小黑洞的话,可以将 (3)、腐蚀膨胀案例 中的腐蚀膨胀倒过来,然后用在如上的二值化图像中,效果会更加明显。

四、形态学梯度

如下所示,此函数实现的效果类似于寻找边缘线:

img_GRADIENT = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_GRADIENT, (x, x))       # 形态学梯度

具体案例程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape
        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY)  # 二值化

        img_GRADIENT = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_GRADIENT, (3, 3))       # 形态学梯度

        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_GRADIENT", img_GRADIENT)      # 显示形态学梯度后的图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述
如上图所示,可以看到边缘断断续续,效果不佳。关于边缘检测,后续我会再写一篇关于图像边缘检测的文章。

五、顶帽和黑帽

1、顶帽

顶帽操作是指开运算与原二值化图作差后再得到一张图像,即消除的噪声点汇总成的图像。opencv-python提供的函数如下所示:

img_TOPHAT = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_TOPHAT, (x, x))   # 顶帽

2、黑帽

黑帽操作和顶帽类似,是指闭运算与原二值化图作差后再得到的一张图像,也是一张消除的噪声点汇总成的图像。opencv-python提供的函数如下所示:

img_BLACKHAT = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_BLACKHAT, (x, x))  # 黑帽

3、顶帽和黑帽案例

具体程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_g = cv2.imread('img/6.jpg', 0)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_g = cv2.resize(img_g, (0, 0), fx=0.5, fy=0.5)  # 改变图像shape
        img_GaussianBlur = cv2.GaussianBlur(img_g, (5, 5), 0)  # 高斯滤波

        t4, img_GaussianBlur_bin = cv2.threshold(img_GaussianBlur, 170, 255, cv2.THRESH_BINARY)  # 二值化

        img_TOPHAT = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_TOPHAT, (3, 3))   # 顶帽
        img_BLACKHAT = cv2.morphologyEx(img_GaussianBlur_bin, cv2.MORPH_BLACKHAT, (3, 3))  # 黑帽

        cv2.imshow("img_GaussianBlur", img_GaussianBlur)    # 显示高斯滤波后的图像
        cv2.imshow("img_GaussianBlur_bin", img_GaussianBlur_bin)    # 显示高斯滤波后的二值化图像
        cv2.imshow("img_TOPHAT", img_TOPHAT)      # 显示顶帽后的图像
        cv2.imshow("img_BLACKHAT", img_BLACKHAT)  # 显示黑帽后的图像

        cv2.waitKey(1)  # 等待时间

图像对应上述程序的imshow,效果如下所示:
在这里插入图片描述
本人是一名学生,目前正在学习中,本篇文章也算是我的学习笔记,如有错误的话还请指正。

猜你喜欢

转载自blog.csdn.net/xztli/article/details/126193076