一、常见图像分割方法
(1)传统算法
-
阈值分割(Thresholding):这是最简单也是应用最广泛的一种分割方法,通过选定一个阈值将图像转换为二值图像,从而分割出目标区域。这种方法适用于图像的前景和背景对比明显的情况。
-
边缘检测(Edge Detection):通过检测图像中亮度变化明显的边缘来识别对象。常用的边缘检测算子包括Sobel、Canny等。
-
区域增长(Region Growing):从一组种子点开始,根据预定的准则(如像素相似性)逐步合并周围的像素,直到满足特定条件。
-
分水岭算法(Watershed):它基于拓扑理论,将图像视为地形表面,利用地形的梯度、洼地等信息来确定分割线,常用于处理接触在一起的物体。
(2)基于深度学习的算法
-
U-Net:适用于医学图像分割,它的结构形似“U”,能够通过深层网络精确地分割图像中的微小结构。
-
Mask R-CNN:是在Faster R-CNN的基础上拓展的,不仅可以识别图像中的对象,还可以为每个识别出的对象生成高质量的分割掩码。
-
DeepLab系列:采用了空洞卷积来控制感受野的大小,并引入了CRF(条件随机场)来改进分割的边缘细节。
二、常见术语
(1)语义分割与实例分割
(2)交叉熵损失函数
想象你正在教一群学生区分各种水果,比如苹果、香蕉和橘子。你的目标是确保他们不仅能够正确识别每种水果,而且在不确定的时候能够准确表达出他们的不确定性。换句话说,如果他们面对一个苹果,你希望他们非常自信地说:“这是苹果”,而对于一个看起来既像苹果又像橘子的水果,你希望他们能说:“我认为这可能是苹果,但也有可能是橘子”。
在图像分割的世界里,交叉熵损失函数就像是一个评价系统,用来衡量学生(即我们的模型)的表现。它看看学生的答案(模型的预测)和正确答案(真实标签)有多接近。如果学生对于他们非常确定的水果给出了正确的答案,他们会得到很高的分数。如果他们对某个答案非常确定,但却是错误的,他们会失去很多分数。最关键的是,这个系统鼓励学生(模型)在不确定的时候准确表达自己的不确定性,而不是盲目猜测。
具体到技术细节,交叉熵损失函数通过比较模型对每个像素分类的概率分布和真实的分类(哪个像素属于哪种类别)来工作。如果模型对某个像素属于其真实分类的概率预测得很高,那么交叉熵损失就低,意味着模型的表现好。反之,如果模型对某个像素的预测概率分布和真实分类差别很大,交叉熵损失就高,意味着模型的表现不好。
简而言之,交叉熵损失函数就像是一个老师,通过评分系统来指导学生(模型)更准确、更自信地识别每一块像素所代表的是哪种“水果”(类别),并在他们不确定的时候鼓励他们表达出这种不确定性。
交叉熵损失函数的公式如下:
这里的公式是针对二分类问题的一种表达,其中(ytrue)是真实的标签(0或1),而(ypred)是模型预测的概率(即模型认为样本为类别1的概率)。公式中的(pos_weight)是一个用来平衡正负样本权重的系数,其中num_neg
是负样本的数量,而num_pos
是正样本的数量,该设置的目的是为了使得损失函数中正样本的损失与负样本的损失在数量上更加平衡。
最好理解公式的方法,往往不是想它的推导,直接看他可能输出结果的情况反而更能把握公式:
- 当真实标签(ytrue=1)时,公式变为(-log(ypred))。这部分衡量的是当样本为正样本时,模型预测正确的置信度。如果(ypred)接近1(模型非常确信样本为正样本),那么损失趋近于0;如果(ypred)远离1,损失就增大。
- 当真实标签(ytrue=0)时,公式变为(-log(1 - ypred))。这部分衡量的是当样本为负样本时,模型预测正确的置信度。如果(ypred)接近0(模型非常确信样本为负样本),那么损失趋近于0;如果(ypred)远离0,损失就增大。
(3)MIOU评估标准
你有一张图片,你的任务是区分出图片中的猫、狗和背景。图像分割技术可以帮助你准确地标出猫和狗的轮廓,以及它们不属于的区域(即背景)。
在图像分割中,MIOU(平均交并比)是一个非常重要的评估标准,用来衡量模型分割结果的精确度。要理解MIOU,我们首先需要了解什么是交并比(IOU,Intersection over Union)。
想象你在一张纸上画了一个圆来表示模型预测的猫的区域(预测区域),然后在同一个位置,用不同颜色画了另一个圆,这次是准确标记猫所在的真实区域(真实区域)。这两个圆可能会有一部分重叠。在这个情景中:
- 交集(Intersection):两个圆重叠的区域,即模型预测正确的部分。
- 并集(Union):两个圆覆盖的总区域,即所有预测的区域加上所有真实的区域,减去交集部分(因为交集被计算了两次)。
IOU 就是这两个圆重叠区域(交集)与它们总覆盖区域(并集)的比值。这个比值越接近1,说明模型的预测越准确。
现在,如果我们在处理多个类别(比如猫、狗、背景),MIOU(Mean IOU,平均交并比)就是对每个类别计算IOU然后取平均值。换句话说,我们分别计算猫、狗、背景的IOU,然后计算这些IOU的平均值来得到MIOU。这样就可以得到一个全面的评估指标,反映模型在所有类别上的平均表现。
三、详细介绍
1.传统算法
1)阈值分割
1]详细原理
想象你正在玩一款分类游戏,其中你的任务是将一堆不同颜色的球分开,假设有红色和蓝色两种球。一个简单的策略是设置一个规则:颜色深于某个特定蓝色阈值的球算作蓝色,浅于这个阈值的算作红色。这就是阈值分割在图像处理中的基本思想。
在图像分割的背景下,你可以把每个像素点的亮度或颜色强度想象成球的颜色。阈值分割就是选择一个亮度或颜色强度的“阈值”。然后,根据这个阈值将图像的每个像素分为两组:一组是亮度或颜色强度高于阈值的像素,另一组是低于阈值的像素。这样,图像就被分割成了两个部分,其中一个部分包含所有背景像素,另一个部分包含所有前景(目标对象)像素。
举个例子,假设你有一张黑白照片,想要从中分离出所有的文字(文字是黑色的,背景是白色的)。如果你设置一个合适的阈值,比如说灰度值为120(在0到255的灰度范围内,0表示黑色,255表示白色),那么所有灰度值小于120的像素(较暗的部分,即文字部分)会被分为一组,而灰度值高于120的像素(较亮的部分,即背景)会被分为另一组。通过这种方式,你就可以“分割”出图像中的文字部分。
2]完整代码
import cv2
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
image_path = r"C:\Users\Lenovo\PycharmProjects\Graduation_Project_XZE\cell.jpg"
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
if img is None:
print("Error: Image could not be loaded. Please check the path.")
else:
# 应用阈值分割
_, thresholded_img = cv2.threshold(img, 190, 255, cv2.THRESH_BINARY)
images_combined = np.hstack((img, thresholded_img))
plt.figure(figsize=(10, 5)) # 设置图像大小
plt.imshow(images_combined, cmap='gray') # 显示图像
plt.title("原图与处理后的图像") # 设置图像标题
plt.xticks([img.shape[1] // 2, img.shape[1] + img.shape[1] // 2], ["原图", "处理后的图像"])
plt.yticks([]) # 禁用y轴刻度
plt.show()
3]运行结果
2)边缘检测算法
1]详细原理
想象一下你有一张满是各种形状和颜色的图片,而你的任务是用一支笔描出这些形状的边缘,让每个形状都清晰可辨。在图像分割中,边缘检测方法就像是这支笔。它帮助我们找到图片中各个物体或区域的边界。
边缘检测工作的原理基于这样一个事实:在图像中,边缘通常是亮度、颜色或纹理发生显著变化的地方。比如,一只黑猫坐在白色沙发上,猫和沙发的边界就是一个边缘,因为那里黑色和白色形成了明显的对比。
边缘检测方法会通过一系列计算,试图找到这些明显变化的地方。它会“审视”图片上的每一个小点,检查这个点与周围点在颜色或亮度上是否有大的不同。如果有,这个点可能就是某个边缘的一部分;如果没有,那它就属于某个平滑的区域。
完成这些计算后,我们会得到一系列标记了所有找到的边缘的点。将这些点连接起来,就像为图片中的物体描边一样,这样我们就能清晰地看到每个物体的形状和位置了。这个过程对于理解和分析图像内容非常有帮助,比如在自动识别图片中的物体时。
2]完整代码
import cv2
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
image_path = r"C:\Users\Lenovo\PycharmProjects\Graduation_Project_XZE\cell.jpg"
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用Canny算法进行边缘检测
edges = cv2.Canny(gray, 100, 200)
combined = np.hstack((img, cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)))
3]运行结果
3)区域增长算法
1]详细原理
图像分割中的区域增长方法就像是在玩一场扩张领土的游戏。想象你手里有一张由很多小方块(像素)组成的地图(图像),而每个小方块都有自己的颜色(灰度值)。游戏的目标是从地图上一个指定的起点(种子点)开始,逐步扩大你的领土,将相似颜色的小方块纳入你的区域,直到没有相似的小方块可以添加。
在开始游戏前,你需要确定两件事:一是从哪个小方块开始扩张(也就是选择一个种子点),二是怎样判断哪些小方块的颜色与你当前区域的颜色足够相似,可以被纳入你的领土(通常是通过设置一个阈值,比如颜色差异在这个阈值内的就认为是相似的)。
游戏开始后,你就从种子点出发,检查周围的小方块。如果周围的小方块颜色与种子点相似,就将它们标记为自己的领土,并且这些新加入的小方块也会成为新的种子点,接着再检查这些新种子点周围的小方块,看是否有符合条件的可以继续加入。这个过程一直重复,直到没有更多相似的小方块可以加入为止。
2]完整代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def region_growing(img, seed, thresh):
"""
区域增长算法。
参数:
- img: 灰度图像
- seed: 种子点的坐标 (x, y)
- thresh: 阈值,用于确定像素是否属于当前区域
返回: 分割后的图像
"""
height, width = img.shape
mask = np.zeros_like(img) # 分割结果的遮罩
seeds = [seed] # 待处理的种子点列表
while seeds:
x, y = seeds.pop(0)
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if dx == 0 and dy == 0:
continue
nx, ny = x + dx, y + dy
if nx >= 0 and nx < width and ny >= 0 and ny < height:
if mask[ny, nx] == 0 and abs(int(img[ny, nx]) - int(img[y, x])) < thresh:
mask[ny, nx] = 255
seeds.append((nx, ny))
return mask
image_path = r"C:\Users\Lenovo\PycharmProjects\Graduation_Project_XZE\cell.jpg"
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# 应用区域增长算法
seed_point = (img.shape[1] // 2, img.shape[0] // 2) # 选择图像中心点作为种子点
segmented_img = region_growing(img, seed_point, 10) # 阈值设置为10
# 拼接原图和处理后的图像
combined_img = np.hstack((img, segmented_img))
# 显示图像
plt.imshow(combined_img, cmap='gray')
plt.title("原图与区域增长结果")
plt.axis('off')
plt.show()
3]运行结果
4)分水岭算法
1]详细原理
你现在有一张特别复杂的地形图,上面有山峰、山谷、平原等等。你的目标是找出地图上所有山谷的位置,并且确定它们的边界。
分水岭算法可以被想象成一种虚拟的洪水过程。一开始,整个地图是干燥的,然后我们开始从最低点——也就是最深的山谷——注水。随着水位的不断上升,水开始填满一个个山谷。但是,我们在不同山谷之间放了些隐形的墙壁,这样水就只能在各自的山谷内上升,而不能越过边界混合到别的山谷里。
随着时间的推移,水继续上涨,并开始接触到山谷的边缘(即山脊)。当两个不同山谷的水几乎要相遇时,我们就在它们之间建立一堵真正的墙——这就是“分水岭”。这样,每个山谷都被水完全填满,直到达到山脊,而所有的山谷都被墙壁明确分隔开来。
在图像分割的语境中,我们把图像想象成一张地形图,其中每个像素的值(比如亮度)代表该位置的“高度”。低值像素代表低洼地区(山谷),而高值像素代表高地(山峰)。分水岭算法就是用来找出这些“山谷”,并确定它们的边界,以此来划分图像中的不同区域或对象。
这种方法特别适用于图像里对象相互靠得很近或者接触的情况,因为它能够精确地找到并标记出对象的边界。不过,这个算法也有挑战,比如如果图像中有很多噪点或者细节过多,可能会产生很多“假的”山谷,导致分割结果过于碎片化。因此,在使用分水岭算法之前,通常需要对图像进行一些预处理,比如平滑处理,以减少这种情况的发生。
2]完整代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 读取图像
img = cv2.imread(r'C:\Users\Lenovo\PycharmProjects\Graduation_Project_XZE\cell.jpg') # 请替换为你的图片路径
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 应用高斯模糊
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 使用直方图均衡化
equalized = cv2.equalizeHist(blurred)
# 应用自适应阈值进行分割
thresh = cv2.adaptiveThreshold(equalized, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 11, 2)
# 使用形态学变换去噪声
kernel = np.ones((2, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 寻找前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.001 * dist_transform.max(), 255, 0)
# 寻找未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 标记标签
ret, markers = cv2.connectedComponents(sure_fg)
# 增加1所有的背景区域变为0,以确保背景不是0, 而是1
markers = markers + 1
# 用分水岭算法标记未知区域
markers[unknown == 255] = 0
markers = cv2.watershed(img, markers)
img[markers == -1] = [255, 0, 0]
# 绘制结果
plt.figure(figsize=(12, 6))
plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('原图像')
plt.subplot(122), plt.imshow(markers), plt.title('分水岭算法结果')
plt.show()
3]运行效果
2.基于深度学习的算法
1)U-Net
1]详细原理
1))编码与解码
想象一下,你有一张非常详细的城市地图,但这张地图太大了,以至于你需要折叠它才能方便地携带。现在,假设你的任务是把这张大地图转换成一种格式,既能让你容易地带着走,又能让你在需要时迅速展开查看所有的细节。这个任务,实际上和U-net在图像分割中所做的“编码-解码”过程相似。
编码过程(压缩地图)
编码过程,可以看作是不断折叠地图的过程。在这个阶段,U-net逐步对图像进行下采样(想象为减少地图的尺寸),每一步都在提取和总结图像中的信息与特征,同时也在丢失一些不必要的细节。就像你把地图折叠起来,试图只保留最重要的街道和标志,而去除一些小巷和细节。这个过程中,我们获得了图像的高级特征(比如图像中有什么物体、物体的大概形状等),但丢失了精确的边界和细节信息。
解码过程(展开地图)
接下来是解码过程,这个过程可以看作是逐步展开地图,试图恢复其原始大小和细节的过程。在这一阶段,U-net通过逐步上采样(想象为增加地图的尺寸)和添加从编码过程中保存下来的信息(这些保存的信息有助于恢复丢失的细节),来重新构造图像。这就像是你尝试将地图展开,同时根据记忆和一些关键点(编码阶段保存的信息)来恢复地图中的每个小巷和细节。
由上述示意图,大家应该明白它为什么取名叫“U”net了,通过这样的“U型”的编码-解码过程,U-net不仅能够理解图像中有什么(通过编码过程提取的高级特征),还能准确地定位这些对象在图像中的位置(通过解码过程恢复的细节)。最终,U-net输出的是一个与原始图像同样大小的图像,其中每个像素都被分配了一个类别标签,告诉我们这个像素属于图像中的哪个对象。
2))特征融合与拼接
特征融合(用便签保存关键点)
在U-net的编码阶段,模型在把地图折叠起来的同时,会使用便签标记出一些重要的地标和街区。为什么要这么做呢?因为当你折叠地图时,一些细节就会隐藏在折叠里面,不再可见。但是,这些便签上的标记能帮助我们记得那些一旦地图被展开就需要恢复的重要信息。
拼接(解码时参考便签)
到了解码阶段,也就是我们逐步展开地图的时候,我们就会去看这些便签。这些便签告诉我们哪里有之前隐藏起来的重要细节,比如特定的路口或建筑物。在U-net中,这个过程是通过将编码阶段保存下来的特征图(便签上的信息)与解码阶段当前的特征图(已经部分展开地图)进行拼接实现的。
2]优缺点及改进
1))优点
- 精确的分割能力:U-net因其出色的细节保留能力而闻名。就像我们前面提到的,通过编码-解码过程和特征融合,U-net能够在图像中精确地定位和分割出感兴趣的对象。
- 需要的数据量相对较少:对于许多深度学习模型来说,需要大量的标注数据来学习。而U-net借助于其数据增强策略和有效的学习机制,能够在相对较少的训练样本上也表现出色。
- 适用性广泛:虽然U-net最初是为医学图像分割设计的,但它已被成功应用于各种类型的图像分割任务,表现出了极好的适用性和灵活性。
2))缺点
- 可能的过拟合风险:虽然U-net可以在较少的数据上表现良好,但如果训练数据过于有限且多样性不足,模型仍然可能面临过拟合的风险。
- 细节恢复的局限性:在某些情况下,尽管U-net在细节恢复方面表现出色,但仍有可能未能完全捕获极其微小或复杂的细节。
3))改进版:U-net++
基于之前介绍U-net时的地图的例子,U-net像是一个精心设计的过程,可以帮助我们折叠和展开一个城市地图,并确保城市的重要特征(如街道、建筑等)在整个过程中得到保存和准确恢复。U-net++可以看作是这个比喻中的一个高级版地图工具,它提供了一些额外的智能功能,让地图的折叠和展开过程更加精细和准确。
U-net的地图工具:
- 折叠时标记重要点(编码器):在一开始折叠地图时,U-net会用标记记录下重要的地标和地区。
- 展开时参照标记(解码器):接着在展开地图时,U-net会参照这些标记来还原这些重要的点。
U-net++的高级地图工具:
- 多级标记系统:U-net++在U-net的基础上增加了一个多级标记系统。在折叠地图的每个阶段,U-net++都会进行多次检查和标记,确保没错过任何细节。
- 多次检查(深度监督):每折叠一次,U-net++都会回头检查以前的标记是否还适用,是否需要更新信息。这样做可以确保即使在多次折叠后,重要的细节仍然可以被完整地保留下来。
- 细节优化(密集连接):U-net++在地图的折叠和展开过程中使用密集连接,这意味着每一次标记不仅仅记录当前的细节,还会考虑前面所有的细节。这就像是在创建一个非常详细的参考系统,确保在最终还原地图时,每一个小巷和建筑都被精确地放置在正确的位置。
2)Mask R-CNN
1]详细原理
不妨继续之前U-net那个地图的比喻,现在,你的目标不仅是把这张庞大的地图折叠起来方便携带,还要在需要时能迅速找到某个特定的建筑,并且标出它的确切边界,比如画出它的轮廓。
这里,Mask R-CNN的工作方式可以用来处理一个更进一步的挑战:在这张复杂的地图中,不仅要识别和标记出每一个重要的地标,还要准确勾画出它们的具体形状。首先,它像是你用放大镜扫描整个地图,寻找可能隐藏着有趣建筑的区域,即“区域建议网络”(RPN)部分。这就像是在地图的每一个角落里寻找那些值得注意的地标——不仅是看它们在哪里,而且要注意它们的大致轮廓。
接着,一旦我们用放大镜找到了这些特别的地方,Mask R-CNN的下一步就是细致地勾画出每一个地标的轮廓。这就相当于你不仅要标记出这些建筑在地图上的位置,还要非常精确地描绘出它们的外形,无论是尖塔、圆顶,还是复杂的外墙装饰。在这个过程中,Mask R-CNN通过一个称为“mask branch”的特殊部分来完成这项工作,它能够对每一个识别出的地标生成一个“掩模”,精确地描绘出其形状。这就好比是在地图上为每个建筑画出一个详细的轮廓,不仅让你知道这座建筑在哪里,还能让你看到它的具体形状。
总的来说,Mask R-CNN就像是一个高级的地图阅读工具,不仅能告诉你每个地标的位置,还能展示它们的精确形状。
2]优缺点及改进
1))优点
-
高度精确的定位能力: 就像一个擅长在繁杂的城市地图中精确找到每个地标并且能够准确描绘出它们边界的专家。Mask R-CNN不仅可以识别出地图上的建筑和街道,还能够绘制出它们的具体形状,提供了非常详尽的信息。
-
灵活应对不同的任务: 像是一个多才多艺的向导,不仅能告诉你地标在哪里(目标检测),还能告诉你地标的形状(实例分割)。这种能力让它在处理需要同时进行物体检测和更细致分析的复杂图像时表现出色。
-
强大的泛化能力: 就像一个经验丰富的旅者,无论是在新的城市还是陌生的环境中,都能凭借过往的经验快速适应并准确识别和解释地图信息。Mask R-CNN通过大量的训练数据,能够泛化到各种不同的图像和任务上。
2))缺点
-
处理速度: 想象在分析一张复杂城市地图时,你需要逐个检查每个地标,同时绘制它们的轮廓。这是一项非常耗时的工作。同样,Mask R-CNN在处理高复杂度图像时,尤其是需要实时分析的情况下,其速度可能不满足实际应用的需求。
-
资源消耗: 使用Mask R-CNN就像是需要一个携带大量绘图工具和参考资料的重装备探险队,而不是一个只携带轻便背包的单人旅行者。换句话说,Mask R-CNN对计算资源的需求较高,需要较强的硬件支持才能发挥最佳性能。
-
训练难度: 正如一个探险队在出发前需要进行复杂的准备和长时间的训练一样,Mask R-CNN的训练也是一个资源密集和时间密集的过程。它需要大量的标注数据和计算资源,而且调整其众多参数以达到最佳性能也是一项挑战。
3))改进版:PANet
-
Bottom-up Path Augmentation(从底向上的路径增强)
想象你正在阅读一张非常详细的城市地图,但这次,你不仅想知道每个地标的位置和轮廓,你还想了解它们的纹理和细节,比如建筑的材料或者街道的铺设方式。Mask R-CNN好比是有一支能在高空俯瞰大景观的团队(高层的特征图),同时也需要一个地面团队(低层的特征图),后者可以近距离观察细节。
PANet通过引入Bottom-up Path Augmentation,实际上就是建立了一条从地面团队到高空团队的直通路径,让低层的细节信息能够直接影响到高层的整体观察。这样做的结果是,你现在可以更准确地定位每个地标,并且对它们的纹理和外观有更清晰的认识。
-
Adaptive Feature Pooling(自适应特征池化)
回到地图的例子,想象你现在需要同时从不同的高度来观察每个地标,既需要从高空获取整体轮廓,也需要从较低的高度捕捉更多细节。在原始的Mask R-CNN中,对每个地标的观察好比只从一个固定的高度进行。而PANet引入的自适应特征池化,就好比是让你能够同时从多个高度观察,这样可以更全面地收集每个地标的信息。
通过这种方式,PANet能够综合不同层级的信息来做出更准确的预测。就像是你现在拥有了一组从不同高度拍摄的照片,这些照片共同帮助你更好地理解每个地标的特点。
-
融合了FCN式的预测和全连接式的预测来提升Mask的质量
最后,想象你不仅要识别出地图上的地标,还要绘制出它们精确的边界。在这里,PANet通过同时利用FCN(全卷积网络)式的预测和全连接式的预测,就好比是在使用两套绘图工具。FCN式预测关注每个地标的局部细节,而全连接式预测则从更宏观的角度考虑地标的整体形态。
这样的结合使得PANet在生成每个地标的“掩模”时,既考虑到了细节的精确性,也没有忽视整体的形状和上下文信息,从而提供了更高质量的结果。
3]与Fast R-CNN的区别
同样基于之前地图的比喻,Fast R-CNN能快速地在城市地图上识别和分类有趣的地区(例如,特定的建筑或地标),同时确定这些建筑的具体位置(即,它们在地图上的边界框)。Fast R-CNN的核心在于它的效率和准确性:一旦你用一个区域建议步骤(这个步骤在Fast R-CNN之前进行,可能使用了如Selective Search的方法)来确定了哪些地区可能值得探索,它就能迅速给出这些建议地区的详细信息,包括它们是什么以及它们的具体位置。
Fast R-CNN与Mask R-CNN方法的区别主要有以下三点:
- 实例分割能力:最直接的区别是Mask R-CNN引入了实例分割能力,能够为每一个识别的对象生成详细的分割掩模,而Fast R-CNN只能进行对象检测和分类。
- 结构上的创新:为了支持实例分割,Mask R-CNN对Fast R-CNN的结构进行了改进,引入了一个额外的并行分支。这个分支专注于生成分割掩模,同时还保持了对象检测和分类的功能。
- 精度和复杂度:由于Mask R-CNN在Fast R-CNN的基础上增加了实例分割功能,它在处理细节和复杂场景时提供了更高的精度,但这也意味着在实现和计算上更为复杂。
综上所述,虽然Mask R-CNN在Fast R-CNN的基础上引入了实例分割的强大能力,两者都在目标检测领域内发挥着重要的作用。通过增加额外的分割分支,Mask R-CNN能够提供更加详细和全面的信息,使其在需要进行精确形状理解的应用场景中尤为有用 。
3)deeplab
1]详细原理
同样还是之前的例子,你希望能够不仅识别出每个区域的大致位置,还要精确到每个建筑、每条街道乃至每棵树的具体轮廓。DeepLab模型就像是一支非常高级的笔,能帮你在这张地图上精确地勾勒出所有这些细节。
1. 空洞卷积(Atrous Convolution)
使用空洞卷积就好比在画笔上装了一个特殊的透镜,这个透镜能让你在不丢失地图上的细节信息的同时,还能“放大”来观察更广阔的区域。简单来说,空洞卷积允许模型在保持计算效率的情况下,捕获更广泛的上下文信息,而不是仅仅关注于紧密的局部区域。
2. ASPP(空洞空间金字塔池化)
如果说空洞卷积是在你的画笔上装了一个透镜,那么ASPP就好比是给你的画笔增加了一套能够自动调整透镜焦距的能力。通过使用不同大小的空洞卷积,ASPP能够在多个尺度上捕获图像的特征,这就像是同时从鸟瞰视角和地面视角观察城市,让你能更全面地理解城市的布局和细节。
空洞卷积与传统卷积的区别主要有以下两个方面:
1. 空间采样率
- 传统卷积:在执行传统卷积时,卷积核(或过滤器)中的每个单位会按照顺序紧密地作用于输入数据的每个部分。这意味着,如果你有一个3x3的卷积核,它将会依次覆盖输入数据的3x3区域,每次移动一个单位(步长为1时)。
- 空洞卷积:空洞卷积通过在卷积核的元素之间引入“空洞”(即增加空间间隔)来扩大其作用范围,而不增加额外的计算成本或参数数量。例如,一个3x3的卷积核,如果使用空洞率(dilation rate)为2,那么实际上它将覆盖一个7x7的区域,其中卷积核的元素不是紧挨着的,而是通过空格隔开。
2. 感受野(Receptive Field)
- 传统卷积:通过堆叠多层传统卷积层,网络的感受野逐渐增大,能够覆盖输入数据中更大的区域。然而,这种方法增加了网络的深度和计算复杂度。
- 空洞卷积:空洞卷积通过扩大卷积核的感受野来直接增加单层的感受野大小,而不需要增加网络的深度或复杂度。这使得空洞卷积特别适用于需要捕获广泛上下文信息的任务,如语义分割。
3. 上采样和精细分割
完成了宏观和微观视角的探索后,DeepLab还需要将这些信息组合起来,细致地勾勒出每个区域的边界。这一步骤就像是使用放大镜和细头笔,在地图上精确地绘制出每个区域的轮廓。DeepLab通过上采样(放大特征图)和融合不同尺度的特征信息,确保最终的输出图像既保持了高分辨率,也精确地反映了各个对象的边界。
2]优缺点分析
优点:
-
精确的边界定位:DeepLab像是使用了一支高精度的画笔,在地图上勾勒出每个区域的精确边界。通过空洞卷积和ASPP技术,DeepLab能够在不同尺度捕捉图像的信息,这就像是同时从不同的高度观察地图,能够更精确地分辨出各个建筑和街道的位置。
-
良好的上下文理解能力:空洞卷积让DeepLab具有宽广的视野,能够理解各个元素之间的关系和整体的场景信息,这就像是在考虑一个地区时,不仅仅关注一个小广场,而是理解整个社区的布局。
-
高效的计算:尽管DeepLab能够提供非常详细的分析,但它通过空洞卷积技术减少了参数的数量,使得模型在保留高效率的同时,还能处理大尺寸的图像。
缺点:
-
较高的计算复杂度:虽然DeepLab的设计考虑到了计算效率,但相对于一些更简单的模型,它在处理非常大或者非常复杂的图像时仍然需要较多的计算资源。这就像是在绘制一个非常详尽的城市地图时,需要更多的时间和精力。
-
难以适应小对象:DeepLab在处理图像中的大尺寸对象时表现出色,但对于非常小的对象,比如远处的行人或小型标识,其性能可能会有所下降。这是因为它的设计更注重于捕捉广泛的上下文信息,而可能忽视了一些细小的细节。
-
优化和调整的复杂性:由于DeepLab模型结构的复杂性,对模型进行调整以适应特定的应用需求可能比较困难。这就像是你想要修改已经非常详尽和复杂的城市地图,需要非常细致和专业的知识来保证修改的正确性和有效性。
3]版本发展
自2014年首次亮相以来,DeepLab模型系列在图像分割技术的发展中占据了举足轻重的地位。一路从DeepLab v1到后续版本,每一次迭代都带来了技术上的飞跃,极大地推动了该领域的进步。
1))DeepLab v1
DeepLab v1的推出标志着图像分割技术的一个重要突破。该版本最主要的创新在于引入了空洞卷积(Atrous Convolution),这一技术使得模型能够有效增加感受野,即模型视野中能够观察到的输入范围,而无需增加额外的计算负担或减少图像分辨率。此外,DeepLab v1还采用了基于全连接条件随机场(Fully Connected CRF)的方法,这一策略对于细化图像边缘和提升分割细节的准确度非常有效。这两项创新共同推动了模型在PASCAL VOC2012数据集上获得了第二名的优异成绩。
2))DeepLab v2
随着DeepLab模型的迭代,DeepLab v2在v1的基础上引入了空洞空间金字塔池化(Atrous Spatial Pyramid Pooling, ASPP)机制。ASPP允许模型在不同尺度上捕捉图像特征,通过在几个并行的空洞卷积上操作,每个卷积具有不同的采样率,模型能够更全面地理解图像内容。这种能力使得DeepLab v2在处理不同大小对象时更为有效,从而进一步提升了图像分割的准确度。
3))DeepLab v3
深入发展到DeepLab v3,该版本对ASPP机制进行了一系列的优化,增加了(1 \times 1)的卷积和批量归一化(Batch Normalization, BN)。这些改进不仅提高了模型对图像特征的捕获能力,还优化了训练过程,通过规范化操作减少了内部协变量偏移,从而加速了模型的收敛速度并提升了性能。这一版本的DeepLab模型因其在图像分割领域的高效表现而被广泛认可。