python --opencv图像处理形态学(开运算、闭运算、梯度运算、顶帽运算、黑帽运算)

引言

前面介绍了图像形态学的两种基础算法,图像腐蚀和图像膨胀,本篇接着介绍图像形态学中的开运算、闭运算以及梯度运算。
需要了解清楚图像的腐蚀与膨胀基础原理,不然真的没办法理解开运算和闭运算。

第一件事情还是给图像增加噪声,思路沿用之前加噪声的思路,使用 Numpy 给图片添加黑白两种噪声点,代码如下

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv.imread("demo.png", cv.IMREAD_UNCHANGED)
source = cv.cvtColor(img, cv.COLOR_BGR2RGB)
rows, cols, chn = source.shape

# 加噪声-白点噪声
for i in range(500):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    source[x, y, :] = 255

# 图像保存 白点噪声图像
cv.imwrite("demo_noise_white.jpg", source)
print("白点噪声添加完成")

# 重新读取图像
img1 = cv.imread("demo.png", cv.IMREAD_UNCHANGED)
source1 = cv.cvtColor(img1, cv.COLOR_BGR2RGB)

# 加噪声-黑点噪声
for i in range(1000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    source1[x, y, :] = 0

# 图像保存 黑点噪声图像
cv.imwrite("demo_noise_black.jpg", source1)
print("黑点噪声添加完成")

# 显示结果
titles = ['White Img','Black Img']
images = [source, source1]

# matplotlib 绘图
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()

在这里插入图片描述

开运算

图像开运算实际上是一个组合运算,开运算是图像先进行腐蚀,再进行膨胀的运算。

图像被腐蚀后,去除了噪声,但是也压缩了图像;接着对腐蚀过的图像进行膨胀处理,使得刚才在腐蚀过程中被压缩的图像得以恢复原状。

下面是一个图像开运算的流程图:
在这里插入图片描述

开运算的一些特性:

  • 开运算能够除去孤立的小点,毛刺和小桥,而总的位置和形状不便。
  • 开运算是一个基于几何运算的滤波器。
  • 结构元素大小的不同将导致滤波效果的不同。
  • 不同的结构元素的选择导致了不同的分割,即提取出不同的特征。
  • 我们先不管开运算 OpenCV 为我们提供的函数是什么,先使用前面介绍过的图像腐蚀与膨胀处理看下结果

案例:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo_noise_white.jpg", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5),np.uint8)

# 图像腐蚀
erode_img = cv.erode(source, kernel)

# 图像膨胀
dilate_result = cv.dilate(erode_img, kernel)

# 显示结果
titles = ['Source Img','Erode Img','Dilate Img']
images = [source, erode_img, dilate_result]

# matplotlib 绘图
for i in range(3):
   plt.subplot(1, 3, i+1), plt.imshow(images[i],'gray')
   plt.title(titles[i])
   plt.xticks([]),plt.yticks([])

plt.show()

在这里插入图片描述
可以看到降噪的效果还是不错的。

接着看 OpenCV 为开运算提供的函数。

图像开运算主要使用到的函数是 morphologyEx() 它是形态学扩展的一组函数,而其中的 cv.MORPH_OPEN 对应的是开运算。

使用时语法如下:

dst = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)
  • src:原图形
  • cv2.MORPH_OPEN:表示开运算
  • kernel:卷积核

我们再使用 morphologyEx() 函数去重新实现下刚才的图像开运算,看下和之前的结果有啥区别:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo_noise_white.jpg", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5),np.uint8)

#图像开运算
dst = cv.morphologyEx(source, cv.MORPH_OPEN, kernel)

# 显示结果
titles = ['Source Img','Dst Img']
images = [source, dst]

# matplotlib 绘图
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()

在这里插入图片描述
至少从肉眼的角度上看不出来和之前的方式有啥区别,实际上也没啥区别。

闭运算

与开运算相反的是闭运算,闭运算是图像先膨胀,后腐蚀,它有助于关闭前景物体内部的小孔,或物体上的小黑点。

先看下图像闭运算的流程图:

在这里插入图片描述

闭运算的一些特性:

  • 闭运算能够填平小湖(即小孔),弥合小裂缝,而总的位置和形状不变。
  • 闭运算是通过填充图像的凹角来滤波图像的。
  • 结构元素大小的不同将导致滤波效果的不同。
  • 不同结构元素的选择导致了不同的分割。

首先还是用 dilate()erode() 函数实现一下图像闭运算,代码如下:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo_noise_black.jpg", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5),np.uint8)

# 图像膨胀
dilate_result = cv.dilate(source, kernel)

# 图像腐蚀
erode_img = cv.erode(dilate_result, kernel)

# 显示结果
titles = ['Source Img','Dilate Img','Erode Img']
images = [source, dilate_result, erode_img]

# matplotlib 绘图
for i in range(3):
   plt.subplot(1, 3, i+1), plt.imshow(images[i],'gray')
   plt.title(titles[i])
   plt.xticks([]),plt.yticks([])

plt.show()

在这里插入图片描述
如果想要使用形态学扩展的函数 morphologyEx() 则需要把里面的参数换成 MORPH_CLOSE ,同样,既然是形态学扩展函数,那么图像腐蚀和图像膨胀也有对应的参数:

  • 图像腐蚀:MORPH_ERODE
  • 图像膨胀:MORPH_DILATE

接着还是使用 MORPH_CLOSE 参数来实现下图像的闭运算:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo_noise_black.jpg", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5),np.uint8)

# 图像闭运算
dst = cv.morphologyEx(source, cv.MORPH_CLOSE, kernel)

# 显示结果
titles = ['Source Img','Dst Img']
images = [source, dst]

# matplotlib 绘图
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()

在这里插入图片描述

梯度运算

图像形态学的梯度运算和前面的开运算闭运算是一样的,都是组合函数。

梯度运算实际上是图像膨胀减去图像腐蚀后的结果,最终我们得到的是一个类似于图像轮廓的图形。
在这里插入图片描述
梯度运算在 morphologyEx() 函数中的参数是 MORPH_GRADIENT ,示例代码如下:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo.png", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5), np.uint8)

# 图像梯度运算
dst = cv.morphologyEx(source, cv.MORPH_GRADIENT, kernel)

# 显示结果
titles = ['Source Img','Dst Img']
images = [source, dst]

# matplotlib 绘图
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()

在这里插入图片描述

顶帽运算

图像处理顶帽运算是一个获取图像噪声的运算,它是由原始图像减去图像开运算而得到的结果:

顶帽运算 = 原始图像 - 开运算

在这里插入图片描述
图像顶帽运算同样是使用形态学扩展函数 morphologyEx() ,它的参数是 MORPH_TOPHAT ,示例如下:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo_noise_white.jpg", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5), np.uint8)

# 开运算
open = cv.morphologyEx(source, cv.MORPH_OPEN, kernel)

# 顶帽运算
dst = cv.morphologyEx(source, cv.MORPH_TOPHAT, kernel)

# 显示结果
titles = ['Source Img','Open Img', 'Tophat Img']
images = [source, open, dst]

# matplotlib 绘图
for i in range(3):
   plt.subplot(1, 3, i+1), plt.imshow(images[i],'gray')
   plt.title(titles[i])
   plt.xticks([]),plt.yticks([])

plt.show()

在这里插入图片描述

黑帽运算

图像处理顶帽运算是一个获取图像内部的小孔,或者前景色中的小黑点的运算。

它是由图像闭运算减去原始图像的操作:

黑帽运算 = 闭运算图像 - 原始图像

在这里插入图片描述

图像顶帽运算同样是使用形态学扩展函数 morphologyEx() ,它的参数是 MORPH_BLACKHAT ,示例如下:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
source = cv.imread("demo_noise_black.jpg", cv.IMREAD_GRAYSCALE)

# 设置卷积核
kernel = np.ones((5, 5), np.uint8)

# 黑帽运算
dst = cv.morphologyEx(source, cv.MORPH_BLACKHAT, kernel)

# 构造显示结果数组
titles = ['Source Img', 'Black Img']
images = [source, dst]

# matplotlib 绘图
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()

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenCV-Python中,开运算形态学处理的两个基本操作之一。开运算通过先进行腐蚀操作,然后再进行膨胀操作来实现。它的作用包括填充物体空洞、消除噪声、连接邻近物体、平滑边界等。\[2\] 在代码中,使用cv2.morphologyEx函数来进行开运算。参数cv2.MORPH_OPEN表示进行开运算。通过定义一个核(kernel)来指定腐蚀和膨胀的形状和大小。在给定的示例代码中,使用了一个10x10的全1矩阵作为核。\[1\] 具体实现时,先读取原始图像,然后使用cv2.morphologyEx函数进行开运算操作,得到处理后的图像。最后可以通过cv2.imshow函数显示原始图像和处理后的图像,并通过cv2.imwrite函数保存处理后的图像。\[1\] 总结来说,开运算是一种常用的形态学处理方法,可以用于填充物体空洞、消除噪声、连接邻近物体、平滑边界等。在OpenCV-Python中,可以使用cv2.morphologyEx函数来实现开运算操作。\[2\] #### 引用[.reference_title] - *1* *2* *3* [【OpenCV-Python】:形态学操作之开运算运算](https://blog.csdn.net/qq_42856191/article/details/123670455)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像风一样的男人@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值