Python图像处理之膨胀与腐蚀的操作
作者:Warmer_Sweeter 发布时间:2022-10-07 19:47:06
引言
膨胀与腐蚀是图像处理中两种最基本的形态学操作,膨胀将目标点融合到背景中,向外部扩展,腐蚀与膨胀意义相反,消除连通的边界,使边界向内收缩。在本文中我们将了解使用内核的图像膨胀与腐蚀的基本原理。
让我们开始吧,同样我们需要导入必需的库。
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage.draw import circle
from skimage.morphology import erosion, dilation
首先让我们创建一个容易操作的形状--一个简单的圆。
circ_image = np.zeros((100, 100))
circ_image[circle(50, 50, 25)] = 1
imshow(circ_image);
现在让我们定义一个内核。
cross = np.array([[0,1,0],
[1,1,1],
[0,1,0]])
imshow(cross, cmap = 'gray');
将腐蚀函数应用到创建的圆上。
eroded_circle = erosion(circ_image, cross)
imshow(eroded_circle);
图像看起来几乎一模一样。要看到那些微小的差异,我们必须仔细查看图像。
linecolor = 'red'
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax[0].imshow(circ_image, cmap = 'gray');
ax[0].set_title('Original', fontsize = 19)
ax[0].axvline(x = 25, color = linecolor)
ax[0].axvline(x = 75, color = linecolor)
ax[0].axhline(y = 25, color = linecolor)
ax[0].axhline(y = 75, color = linecolor)
ax[1].imshow(eroded_circle, cmap = 'gray');
ax[1].set_title('Eroded', fontsize = 19)
ax[1].axvline(x = 25, color = linecolor)
ax[1].axvline(x = 75, color = linecolor)
ax[1].axhline(y = 25, color = linecolor)
ax[1].axhline(y = 75, color = linecolor)
fig.tight_layout()
我们可以看到,被腐蚀的圆已经略微缩小了。这就是腐蚀一个对象的意义。如果我们对腐蚀函数进行迭代,它的效果会变得非常明显。
def multi_erosion(image, kernel, iterations):
for i in range(iterations):
image = erosion(image, kernel)
return image
ites = [2,4,6,8,10,12,14,16,18,20]
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'Iterations : {ites[n]}', fontsize = 16)
new_circle = multi_erosion(circ_image, cross, ites[n])
ax.imshow(new_circle, cmap = 'gray');
ax.axis('off')
fig.tight_layout()
上图清楚地显示了图像是如何被腐蚀的。现在让我们尝试改变内核,如果我们使用水平线和垂直线内核代替交叉内核会怎样呢?
h_line = np.array([[0,0,0],
[1,1,1],
[0,0,0]])
v_line = np.array([[0,1,0],
[0,1,0],
[0,1,0]])
fig, ax = plt.subplots(1, 2, figsize=(15, 5))
ax[0].imshow(h_line, cmap='gray');
ax[1].imshow(v_line, cmap='gray');
fig.tight_layout()
ites = [2,4,6,8,10,12,14,16,18,20]
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'Horizontal Iterations : {ites[n]}', fontsize = 12)
new_circle = multi_erosion(circ_image, h_line, ites[n])
ax.imshow(new_circle, cmap = 'gray');
ax.axis('off')
fig.tight_layout()
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'Vertical Iterationss : {ites[n]}', fontsize = 12)
new_circle = multi_erosion(circ_image, v_line, ites[n])
ax.imshow(new_circle, cmap = 'gray');
ax.axis('off')
fig.tight_layout()
正如我们所看到的,水平和垂直的腐蚀以不同的方式影响着图像。使用水平内核我们得到一个垂直方向细长的圆;而使用垂直内核我们得到一个水平方向细长的圆。
你可能会奇怪,为什么使用垂直内核,会得到一个水平方向细长的圆呢?
因为腐蚀函数是分别寻找垂直和水平的线条,并慢慢把它们削掉。膨胀函数将会让我们更清晰的理解这一点。
使用下面的函数设置处理的图像、膨胀内核以及迭代次数。
def multi_dilation(image, kernel, iterations):
for i in range(iterations):
image = dilation(image, kernel)
return image
让我们看一下处理后的图像有什么不同。
dilated_circle = multi_dilation(circ_image, cross, 1)
linecolor = 'red'
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax[0].imshow(circ_image, cmap = 'gray');
ax[0].set_title('Original', fontsize = 19)
ax[0].axvline(x = 25, color = linecolor)
ax[0].axvline(x = 75, color = linecolor)
ax[0].axhline(y = 25, color = linecolor)
ax[0].axhline(y = 75, color = linecolor)
ax[1].imshow(dilated_circle, cmap = 'gray');
ax[1].set_title('Dilated', fontsize = 19)
ax[1].axvline(x = 25, color = linecolor)
ax[1].axvline(x = 75, color = linecolor)
ax[1].axhline(y = 25, color = linecolor)
ax[1].axhline(y = 75, color = linecolor)
fig.tight_layout()
可以清楚地看到圆现在已经越过了红线,这清楚地表明它已经扩大了。现在让我们对水平和垂直扩张进行迭代。
ites = [2,4,6,8,10,12,14,16,18,20]
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'Horizontal Iterations : {ites[n]}', fontsize =
12)
new_circle = multi_dilation(circ_image, h_line, ites[n])
ax.imshow(new_circle, cmap = 'gray');
ax.axis('off')
fig.tight_layout()
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'Vertical Iterationss : {ites[n]}', fontsize = 12)
new_circle = multi_dilation(circ_image, v_line, ites[n])
ax.imshow(new_circle, cmap = 'gray');
ax.axis('off')
fig.tight_layout()
现在可以非常清楚地看到,水平扩张增加了图像宽度,而垂直扩张增加了图像高度。
现在我们已经了解了膨胀与腐蚀的基本原理,下面来看一个相对复杂的图像。
complex_image = imread('complex_image.png')
imshow(complex_image);
在上面的图像中,我们看到了水平线、垂直线和圆的混合物。我们可以使用膨胀和腐蚀函数孤立地观察每一种形状。
为了得到圆,我们可以先腐蚀垂直的线,再腐蚀水平的线。但要记住最后要对图像进行膨胀,因为腐蚀函数同样腐蚀了圆。
step_1 = multi_erosion(complex_image, h_line,3)
step_2 = multi_erosion(step_1, v_line,3)
step_3 = multi_dilation(step_2, h_line,3)
step_4 = multi_dilation(step_3, v_line,3)
steps = [step_1, step_2, step_3, step_4]
names = ['Step 1', 'Step 2', 'Step 3', 'Step 4']
fig, ax = plt.subplots(2, 2, figsize=(10, 10))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'{names[n]}', fontsize = 22)
ax.imshow(steps[n], cmap = 'gray');
ax.axis('off')
fig.tight_layout()
同样,下面的代码将得到水平的线。
step_1 = multi_erosion(complex_image, cross, 20)
step_2 = multi_dilation(step_1, h_line, 20)
step_3 = multi_dilation(step_2, v_line,2)
steps = [step_1, step_2, step_3]
names = ['Step 1', 'Step 2', 'Step 3']
fig, ax = plt.subplots(1, 3, figsize=(10, 10))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'{names[n]}', fontsize = 22)
ax.imshow(steps[n], cmap = 'gray');
ax.axis('off')
fig.tight_layout()
为了得到垂直的线,我们可以创建一个新的内核。
long_v_line = np.array([[0,1,0],
[0,1,0],
[0,1,0],
[0,1,0],
[0,1,0]])
step_1 = multi_erosion(complex_image, long_v_line, 10)
step_2 = multi_dilation(step_1 ,long_v_line, 10)
steps = [step_1, step_2]
names = ['Step 1', 'Step 2']
fig, ax = plt.subplots(1, 2, figsize=(10, 10))
for n, ax in enumerate(ax.flatten()):
ax.set_title(f'{names[n]}', fontsize = 22)
ax.imshow(steps[n], cmap = 'gray');
ax.axis('off')
fig.tight_layout()
注意,内核并不局限于本文中提到的这几种,可以根据不同的需求自己定义合适的内核。
来源:https://blog.csdn.net/weixin_38739735/article/details/111940442
猜你喜欢
- 测试图片一、相对路径(报错)使用相对路径插入会报错(确认路径正确无误)import xlwings as xwwb = xw.Book()s
- 一:数据源介绍本篇文章介绍的是使用python实现对葵花8号卫星数据进行自动下载。葵花8号卫星是日本的一颗静止轨道气象卫星,覆盖范围为60S
- 正则表达式的定义在编写处理字符串的程时,经常会遇到在一段文本中查找符合某些规则的字符串的需求,正则表达式就是用于描述这些规则的工具,换句话说
- 首先第一步,打开文件,有两个函数可供选择:open() 和 file()①. f = open('file.txt
- 首先导入包含apriori算法的mlxtend库,pip install mlxtend调用apriori进行关联规则分析,具体代码如下,其
- 前言当前二维码的应用越来越广泛,包括疫情时期的健康码也是应用二维码的典型案例,最近需要通过一张二维码显示较多文本数据,也就是对二维码数据进行
- 图中图准备数据import matplotlib.pyplot as pltfig = plt.figure()x = [1, 2, 3,
- 表结构的修改1、表结构修改后,原来表中已存在的数据,就会出现结构混乱,makemigrations更新表的时候就会出错比如第一次建模型,漏了
- 如何在pytorch中指定CPU和GPU进行训练,以及cpu和gpu之间切换由CPU切换到GPU,要修改的几个地方:网络模型、损失函数、数据
- Instr函数与InstrRev函数大家都应该很熟悉,但是如果你看过《ASP * 站开发实践教程》,你应该注意一下。该书中介绍它们时是很有迷
- 天天敲代码的朋友,有没有想过代码也可以变得很酷炫又浪漫?今天就教大家用Python模拟出绽放的烟花,工作之余也可以随时让程序为自己放一场烟花
- 今天有个哥们问我要是JavaScript函数重名了会有什么后果?开始我没有细想,就说可能会出错吧,可是等我实验完了发现页面没有任何脚本错误提
- 原文地址:30 Days of Mootools 1.2 Tutorials - Day 19 - TooltipsMootools 1.2
- 一些杀毒软件经常会把某些asp文件当成病毒删除,如卡巴斯基杀毒软件就经常把网页中有Microsoft.XMLHTTP 的当作病毒,有时简直防
- 功能:为连连看游戏提供连接算法 说明:模块中包含一个Point类,该类是游戏的基本单元“点”,该类包含属性:x,y,value。 其中x,y
- 场景一、有一个输入金额的场景,这个金额需要验证,验证说明如下:不能为空格;不能为0;不能为汉字;不能为其它字符;不能大于200;唯一可以的是
- Python与Perl,C和Java语言等有许多相似之处。不过,也有语言之间有一些明确的区别。本章的目的是让你迅速学习Python的语法。第
- 上次在blueidea上看到一个元素圆角的实现方法,但是那个太复杂了。于是就自己写了一个函数,可以将元素自动圆角,如div层,表格等。共有四
- 错误提示如下:其实这是一个挺常见的系统报错,缺乏VC++库。我安装的是python3.5.2,这个版本需要的vc版本是2015的了,下载:M
- 导语学习一下golang权限控制,保留一下demo代码作为参考Casbin是什么Casbin是一个强大的、高效的开源访问控制框架,其权限管理