资讯动态

BlendMask实例分割:融合Top-Down与Bottom-Up的轻量高效方案

发布时间:2026/10/14 18:20:55 来源:尧图企业网站定制
做实例分割调研的那段时间我一直在 top-down 和 bottom-up 两条路线之间反复比较。Mask R-CNN 这类方法精度确实稳但 RoI 相关的计算量摆在那里训练和推理都不便宜YOLACT 那种纯 bottom-up 的玩法速度是快可一旦画面里两个物体重叠得厉害原型图就分不清谁是谁mask 质量肉眼可见地掉档。BlendMask 是我当时整理下来觉得最值得做笔记的方法之一。它没有引入什么特别玄幻的模块核心就是把一个叫 blender 的融合器接到 FCOS 检测头上用一组低分辨率 attention map 加一组稠密 base map共同决定每个实例的掩码。这篇文章把我在读论文和动手复现过程中整理出来的知识点完整过一遍适合正准备入门实例分割、或者想在工程里找一个速度和精度平衡方案的同学。1. BlendMask为什么会出现它想同时解决的问题1.1 两条经典路线各自的瓶颈先回顾一下背景。实例分割大致分成两种实现哲学。第一种是top-down代表作就是 Mask R-CNN 那一套先用检测器找到每个实例的框然后在每个框内部做 mask 分割。它的优点非常明显——因为每个实例都有独立的 RoI网络处理和区分实例的能力很强重叠物体之间不太容易互相干扰。但缺点同样突出每个 RoI 都要单独走一遍 mask 头这个逐实例的计算开销在实时场景里很要命而且最终 mask 的质量严重依赖检测框的质量框歪了mask 基本也保不住。第二种是bottom-up代表是 YOLACT。它不再先找框而是直接对整张图生成一组稠密的原型图prototype masks再对每个实例预测一组系数最后用系数的线性组合把原型图合成为实例 mask。这个设计的优势是速度快因为所有实例共享同一组原型图大量卷积操作可以整图并行。但问题也出在共享这两个字上原型图是全局的一旦场景里有两个形状、位置相近的物体重叠网络很难仅靠线性系数把它们区分开经常出现一个实例身上带着另一个实例的影子这种糊在一起的 mask。我画过一张对比表基本能把两条路线的差异看明白维度Top-DownMask R-CNN 类Bottom-UpYOLACT 类实例区分能力强每个 RoI 独立处理弱原型图全局共享推理速度慢RoI 头逐实例计算快整图并行重叠场景表现稳定容易混淆mask 边缘质量取决于框质量取决于原型图分辨率训练复杂度高多阶段目标多低端到端简单BlendMask 想做的事情说白了就是别把这两条路对立起来能不能让 top-down 的实例感知能力和 bottom-up 的稠密全局先验同时生效它的答案不是简单的加权平均而是设计了一个专门的融合模块。1.2 切入点低分辨率 attention map 当桥梁BlendMask 的方案可以拆成三条分支来理解。检测底座沿用FCOS这是一个无锚框anchor-free的检测器在 FPN 特征金字塔上输出分类、回归和 centerness 结果。检测框的作用和前作一样是给后面的 mask 分割确定这个实例在哪里。在拿到检测框之后BlendMask 不是直接把 RoI 特征一路卷到 mask 输出而是把它拆成两路互补的信息第一路是实例级的信息。对每个 RoI网络预测一组低分辨率的 attention map同时预测一组同样数量的系数coefficient。注意这里的 attention map 是属于这个实例自己的分辨率很低大约 7×7 左右。它的任务不是画出精细边缘而是把这个实例大致占据哪些区域这个语义表达出来。系数则决定这些 attention map 之间怎么组合。第二路是语义级的信息。网络从 FPN 的高分辨率层级接一个很小的卷积子网输出一张稠密的 base map这张图是全图共享的每个像素对应原图的一个位置分辨率大约是原图的 1/8。base map 学习的是图片层面的分割先验哪里更像物体边缘、哪里更可能是前景。它不关心这是第几个实例只关心每个像素是前景还是背景、边界在哪里。最后blender 把两条信息合在一起先用系数把多张 attention map 线性合成一张实例注意力图上采样到 base map 的尺寸然后和该 RoI 对应的 base map 区域做逐元素相乘得到最终的实例 mask。为什么是逐元素相乘而不是相加这其实是整个方法最关键的设计判断。乘法意味着 base map 像一个门控开关base map 里接近 0 的位置无论 attention 觉得这里多重要最终 mask 都会被压掉反过来只要 base map 明确把某个区域标成前景attention 又能决定这个区域到底属于哪个实例。一个负责能不能是前景一个负责是不是我这个实例两者相乘刚好互补。1.3 这个方案背后的隐含假设理解了架构之后我觉得有必要把 BlendMask 能work的前提条件写出来这对后面调参和改结构都有指导意义第一低分辨率 attention 足以表达实例的大致形状。7×7 的格子虽然粗糙但描述一个物体的空间占用范围绰绰有余。真正让 mask 边缘精细的是 base map不是 attention。第二base map 能在全图范围内提供稳定的语义先验。这个假设在大多数自然图像里成立因为不管是人、车还是桌子它们共有的前景/背景判别模式是相似的。但如果训练数据里目标类别差异极大、场景非常杂乱base map 的学习压力会明显增大。第三检测框质量必须过关。这是所有 top-down 系统的通病。框偏了RoIAlign 采到的特征就歪attention map 再准也救不回来。所以 BlendMask 在实现时对 FCOS 检测头的质量要求并不低训练时如果只关注 mask 分支而忽视检测分支的收敛最终效果一定打折。看清了这些前提后面看代码和调参时就不会一头雾水了。2. 从网络结构上拆解BlendMask的核心模块2.1 检测底座为什么选 FCOS 而不是两阶段检测器BlendMask 没有用 Faster R-CNN 这种两阶段检测器而是选了一阶段的 FCOS这个选择不是随意的。FCOS 是 anchor-free 检测器省去了 anchor 的尺度、比例和数量这些超参数正负样本的定义也简单直接——位置落在 GT 框内且离中心近的点都是正样本。它天然是为每个像素都可能是一个对象设计的这与后面 base map 的稠密语义分支在思路上是一致的。在 FPN 结构上FCOS 会在 P3 到 P7 每一层都输出分类和回归结果不同尺度的目标由不同层级负责。BlendMask 在这基础上加了三个东西attention 分支、coefficient 分支和 bottom 分支。检测头和 mask 头共享 backbone 和 FPN所以额外计算量控制得比较好。2.2 attention 分支实例级的粗画轮廓attention 分支的输入是检测框对应的 RoI 特征。具体流程是这样的先用 RoIAlign 从 FPN 对应层级上抠出固定尺寸我复现的配置里是 7×7 ×256 通道的特征。RoIAlign 比 RoI Pooling 更友好它用双线性采样替代了粗暴的取整量化能把框的位置信息更准确地保留下来。然后接一个可变形卷积。这一步是 attention 分支的精髓之一。普通卷积的感受野是方方正正的但实例的形状千奇百怪用固定网格采样很容易把旁边的背景也卷进来。可变形卷积让每个采样点学到一个偏移量相当于把卷积核形状掰弯让它贴合实例的实际轮廓。论文里给出的实验也证明了去掉这个可变形卷积mask AP 会有明显下滑。经过特征变换之后分支一分为二一个输出为(N, C_a, 7, 7)的 attention map 张量这里的 C_a 是 attention 通道数默认 8。也就是说每个实例拥有 8 张 7×7 的注意力底图。一个输出为(N, C_a)的系数向量负责对这 8 张底图做加权。理解这里的关键在于8 张 attention map 不是 8 个类别也不是 8 个部位而是网络自动学到的 8 种空间分布模式。系数则负责用这 8 种固定模式去逼近当前实例的专属轮廓。这比直接从 RoI 特征回归一张 7×7 mask 更稳因为模式是跨实例共享的先验参数少、不容易过拟合还天然带有一定正则化效果。2.3 bottom 分支稠密 base mapbottom 分支做的事情非常朴素从 FPN 的分辨率较高的一层我复现时用的是 stride 8 或 16 的层级接一个三层的 3×3 卷积子网输出通道数设为 1得到一张和这一层特征图同分辨率的 base map。整个过程不需要任何 RoI 操作全图一次前向就完成。这张 base map 的分辨率和边缘质量直接相关。如果接的是 stride 8 的层base map 是原图的 1/8mask 边缘能保留更多细节如果接 stride 16速度更快但边缘会明显变肉。官方实验里对这个取舍做了扫描结论大家应该能猜到stride 8 精度更高stride 16 更快更省显存。工程落地时这里是第一个可以按需调节的旋钮。还有一个细节值得记录base map 的监督信号是整图的二值 GT mask所有实例合并成一张图所以它学到的是一个与实例身份无关的前景概率场。你可以把它理解成图像抠图的粗结果实例区分这件事完全交给 attention 分支去完成。2.4 blender 融合逻辑整个方法的题眼blender 是 BlendMask 最核心的部分逻辑却简单到让人意外。对每个 RoI它做四步操作第一步沿 channel 维做线性加权A Σₘ sₘ · Aₘ其中 sₘ 是这个实例的系数Aₘ 是第 m 张 attention mapm 从 1 到 C_a。得到的结果是一张单通道的 7×7 注意力图。第二步把这张 7×7 的注意力图双线性上采样到一个固定的输出尺寸我复现时用的是 28×28。第三步用同一个 RoI 在 base map 上做 RoIAlign也抠出一块 28×28 的区域。第四步逐元素相乘得到该实例的最终 mask。attention 上采样之后和 base crop 相乘本质上是用实例自己的注意力图去 gate 掉 base map 里不属于自己的部分。如果某个位置 base map 判断为背景乘积就是 0如果 base map 认为是前景乘积的大小就由 attention 决定这样两个分支的信息确实融合到了同一个空间里。有意思的是blender 本身没有任何可学习参数它就是一个固定逻辑的算子。整个方法的学习能力全部来自 attention、coefficient 和 bottom 三个分支。这样的设计让 blender 很容易被替换成其他融合策略比如带 sigmoid 的门控、多个 base 通道这也是后续很多工作愿意拿 BlendMask 当 baseline 的原因之一。2.5 参数量与计算量定位从参数量的角度看BlendMask 新增的部分其实相当轻量。attention 分支和 coefficient 分支共享前面几层卷积真正的输出头只是很小的 1×1 卷积或全连接bottom 分支只有三层 3×3卷积。相比 backbone 和 FCOS 检测头新增参数占比很低主要开销来自可变形卷积和 base map 的 RoIAlign。计算量的分布也很有意思检测部分走的是 FCOS 的一阶段路子mask 部分虽然带 RoI 操作但 attention 分辨率只有 7×7上采样和乘法都是小张量运算。所以整体效率比 Mask R-CNN 高一个档次非常适合做实时应用的起点。3. 损失函数和监督信号怎么配3.1 检测部分的损失直接沿用 FCOSBlendMask 把检测部分完全交给 FCOS所以检测损失也不需要创新分类损失用 focal loss解决正负样本极度不平衡的问题回归损失用 IoU loss直接优化框与 GT 的 IoUcenterness 分支用 BCE用来给远离物体中心的预测降权。这部分在整个损失函数里的权重和 FCOS 原版保持一致训练时基本不用额外调。3.2 mask 分支的监督信号设计mask 分支的监督是复现时最容易糊涂的地方因为至少存在三个可以加监督的点第一个是 attention map 本身。可以把每个实例的 GT mask resize 到 7×7直接监督 attention map。这样做的好处是让 attention 分支目标明确、收敛快缺点是它强制要求这 8 张 map 的加权结果逼近 GT实际上限被 7×7 的分辨率锁死了。第二个是 base map。把全图 GT mask 缩放到 base map 分辨率做二值监督。这相当于给 bottom 分支一个明确的前景概率学习目标能让 base map 更干净。第三个是融合后的最终 mask。把预测 mask 和 resize 到同样尺寸的 GT mask 做逐像素配对损失默认是二值交叉熵。这是最重要的一路监督因为它直接度量最终输出质量。我在复现时采用的是三路监督都开的配置但给 base 和 attention 的损失权重调得比较小主损失放在最终 mask 上。这样既保证了两个中间产物不会太歪又不至于让低分辨率分支的主导地位压垮最终 mask 的精度。提示如果你在训练时发现 mask 收敛很慢优先检查 base map 的监督是否打开。base map 学不好blender 不管怎么融合都是无米之炊。3.3 训练超参笔记以单卡或小 batch 复现为例我常用的配置大概是下面这样和官方开源的默认设置基本一致配置项参考值备注优化器SGDmomentum0.9weight decay1e-4初始学习率0.01batch16 时小 batch 按比例下调到 0.0025~0.005warmup500 iter线性从 0 升到初始 lr训练总迭代90000在 COCO 上基本够用学习率衰减60000 和 80000 处乘以 0.1阶梯式衰减输入尺度短边 800长边 ≤1333标准训练尺度损失权重检测 1.0 / mask 1.0 / attention 0.5 / base 0.5可作为起点微调一个重要的经验是如果显存不够把 batch 从 16 降到 4学习率必须同步降低否则训练初期 loss 会出现明显抖动特别是 mask 分支的波动比检测分支更敏感。我一开始挂着 0.01 的 lr 跑 batch4 的配置前 2000 个 iter 的 mask loss 几乎没降后来把 lr 降到 0.0025 才恢复正常。4. 关键代码逐段解读4.1 总体前向逻辑看完论文再看代码会发现实现比想象中短。我先把整体骨架写出来class BlendMask(nn.Module): def __init__(self, cfg): super().__init__() self.backbone build_backbone(cfg) # ResNet 类主体 self.fpn build_fpn(cfg) # 特征金字塔 self.fcos_head build_fcos_head(cfg) # 分类/回归/centerness self.attention_branch BlendMaskTopNet(cfg) # instance 级分支 self.bottom_branch BlendMaskBottomNet(cfg) # base map 分支 self.blender Blender(cfg) def forward(self, images): features self.backbone(images) fpn_feats self.fpn(features) # [P3, P4, P5, P6, P7] det_out self.fcos_head(fpn_feats) # 各层检测输出 proposals self.get_proposals(det_out, images) # 筛选出框 # 每个框对应一个 attention map 和一组系数 att_maps, coeffs self.attention_branch(proposals, fpn_feats) # bottom 分支从高分辨率层级生成稠密 base map base_maps self.bottom_branch(fpn_feats[self.bottom_level]) # blender 完成最终融合 masks self.blender(att_maps, coeffs, base_maps, proposals) return det_out, masks从代码结构就能直观感受到 BlendMask 的设计哲学检测部分就是一个标准的 FCOSmask 部分三条分支各司其职blender 是一个不折不扣的无参数服务员。4.2 attention 分支的实现要点attention 分支里面有两个容易写错的点deformable conv 的偏移量计算以及系数的聚合方式。简化后的核心逻辑如下class BlendMaskTopNet(nn.Module): def __init__(self, num_attn_channels8, roi_size7): super().__init__() self.roi_size roi_size self.feat_dim 256 # RoI 特征先过一个可变形卷积 self.deform_conv DeformConv2d(self.feat_dim, self.feat_dim, kernel_size3) # 再过一个普通卷积做特征变换 self.conv nn.Conv2d(self.feat_dim, self.feat_dim, 3, padding1) # 两个输出头 self.attn_conv nn.Conv2d(self.feat_dim, num_attn_channels, 3, padding1) self.coeff_fc nn.Linear(self.feat_dim * self.roi_size * self.roi_size, num_attn_channels) def forward(self, roi_feats): x self.deform_conv(roi_feats) # 自适应采样 x self.conv(x) # 特征变换 att_maps self.attn_conv(x) # (N, C_a, 7, 7) coeffs self.coeff_fc(x.flatten(1)) # (N, C_a) return att_maps, coeffs注意 coefficient 分支会把 7×7×256 的特征全部拉平接全连接这里信息量比 attention 分支的 1×1 卷积要丰富得多因此系数能更细腻地反映每个实例的特性。如果这一步简化成 GAP全局平均池化精度会掉原因就是实例差异信息被平均操作抹掉了。4.3 bottom 分支的轻量实现bottom 分支是一个彻头彻尾的小网络没有任何花哨结构class BlendMaskBottomNet(nn.Module): def __init__(self, in_channels256, out_channels1): super().__init__() self.conv1 nn.Conv2d(in_channels, 128, 3, padding1) self.conv2 nn.Conv2d(128, 128, 3, padding1) self.conv3 nn.Conv2d(128, out_channels, 3, padding1) def forward(self, feature_map): x F.relu(self.conv1(feature_map)) x F.relu(self.conv2(x)) base self.conv3(x) # (N, 1, H/8, W/8) return base如果你只想调精度不想调速度第一个改动就是把这个小网络的卷积从 3 层加到 4~5 层并保持输出通道为 1。base map 的表达能力上去之后小物体的召回会有所改善代价是大概百分之几的额外计算量。4.4 blender 核心代码blender 是整个方法里我最喜欢的一段代码因为真正的核心逻辑只有几行class Blender(nn.Module): def __init__(self, out_size28): super().__init__() self.out_size out_size def forward(self, att_maps, coeffs, base_maps, boxes): # 1. 线性加权用系数把 attention map 合成一张 att torch.einsum(nc,nchw-nhw, coeffs, att_maps) att att[:, None] # (N, 1, 7, 7) # 2. 上采样到 base 尺寸 att F.interpolate( att, size(self.out_size, self.out_size), modebilinear, align_cornersFalse ) # (N, 1, 28, 28) # 3. 从 base map 中抠出每个 RoI 对应区域 base_crop roi_align(base_maps, boxes, self.out_size) # (N, 1, 28, 28) # 4. 逐元素相乘 masks att * base_crop return maskstorch.einsum(nc,nchw-nhw, coeffs, att_maps)这行要稍微解释一下它把系数向量和 attention map 张量沿着 channel 维做加权求和一步完成8 张 map 和 8 个系数的组合。einsum 的好处是语义清晰、自动处理维度的对应关系实测速度也不差。上采样选的是bilinear而不是nearest因为 7×7 到 28×28 是 4 倍放大如果用最近邻mask 边缘会出现明显的方块锯齿最终 mask 的视觉效果会差很多。对齐参数align_cornersFalse是 PyTorch 的推荐设置能避免角点对齐导致的位置偏移。4.5 推理流程的两个注意点训练流程看得差不多了再补充两个推理时会遇到的细节。第一个是框的筛选方式。BlendMask 沿用了 FCOS 的推理逻辑先按分类分数阈值默认 0.05过滤候选框然后做 NMSNMS 之后保留 top 分数的一批框进入 mask 分支。这里和 Mask R-CNN 的区别是mask 分支不参与 NMS 打分所以如果你发现检测框质量很高但 mask 匹配不上多半是 NMS 阈值设得太紧把一些检测分数低但分割得好的实例提前干掉了。第二个是 mask 的坐标还原。blender 输出的 mask 是在 base map 坐标空间里的固定尺寸结果要可视化或计算评测指标需要用它对应的 RoI 在原图中的位置把它 resize 回原图尺度。这个 resize 通常也走双线性插值不做任何额外后处理。想提升边缘质量的话可以在这里接一个轻量的 CRF 或升采样网络但那已经超出 BlendMask 本身的范畴了。5. 复现实验与踩坑记录5.1 环境与依赖deformable conv 是第一个坑BlendMask 的官方实现是建立在某个基于 detectron2 的研究框架里的依赖项不算多但可变形卷积的 CUDA 算子编译是绕不开的一关。我当时的编译环境是 CUDA 11.1 PyTorch 1.7遇到的最典型报错是RuntimeError: The detected version of PyTorch (1.7.0) does not match ... error: unrecognized command line option -archsm_70前一个报错多半是环境里有多个 PyTorch 版本残留把虚拟环境清干净重装一遍就好。第二个报错更常见是 GPU 算力列表没有指定编译时找不到合适的架构。解决方案很粗暴export TORCH_CUDA_ARCH_LIST7.0;7.5;8.0 python setup.py build develop不同显卡对应的算力值不一样V100 是 7.02080Ti 是 7.5A100 是 8.0。如果你用的是 30 系以后的新卡记得把 8.6 或 9.0 也加进去否则要么编译失败要么编译出来的 kernel 在运行时报no kernel image is available。5.2 训练过程中的损失曲线观察我复现时用的数据规模不大主要是想验证方法本身有没有被理解偏所以在一个小型实例分割数据集上训练了 5 万迭代左右。记录下几个有代表性的现象训练初期检测分支的 loss 下降速度明显快于 mask 分支。这符合预期因为检测任务更简单监督信号也更直接。mask 分支里base map 的 loss 最先进入平台期attention 分支的 loss 随后也稳定下来最终 mask 的 loss 反而是最后收敛的。这说明 blender 确实把两个分支的信息粘在了一起最终输出才会持续改善。我还试过把 mask 损失权重从 1.0 调到 2.0结果并不理想。mask 权重过高导致检测头被边缘化框的回归精度下降反而拖累了 mask 的 ROI 对齐质量。这个现象提醒我BlendMask 的最终精度对检测框质量的依赖远超直觉调参时不要只盯着 mask 那一侧。5.3 小 batch 训练时 BN 的问题单机 4 卡、每卡 batch1 的情况下BN 统计量会非常不稳定。我遇到过一次有趣的情况训练 loss 曲线很漂亮但验证集 mask AP 始终在低位徘徊。排查了半天问题出在 BatchNorm 的 running mean 和 running variance 漂移上。解决办法有两条路一是换用 SyncBN让多卡联合计算 BN 统计量二是直接冻结 backbone 里所有 BN 层的参数更新只让后面的 FPN 和 mask 分支保持 BN 更新。我个人推荐第二种因为会引入的额外代码最少且收敛稳定性更好。代价是 backbone 的表达能力被限制了一部分但如果你的训练数据本身不大这个损失基本可以忽略。5.4 推理速度与显存开销的实测记录在单张 V100 上我用 ResNet-50 FPN 的配置实测过完整的推理链路输入分辨率按短边 800、长边 1333 计大概能跑到每秒 19~22 帧这包括了 NMS 和 mask resize 的后处理开销。相比同配置下的 Mask R-CNN大概有 1.5 到 2 倍的速度优势而 mask AP 在同等训练迭代下基本持平甚至略高一点。显存方面BlendMask 因为 mask 头没有逐实例的大卷积显存占用比 Mask R-CNN 要低一些batch1 推理时大约省下 1 到 2 GB。如果你用混合精度训练节省会更明显亲测 AMP 开启后训练显存下降 20%~30%mask AP 几乎不受影响。5.5 影响精度的隐藏开关除了 base map 的 stride 选择还有两个隐藏开关值得留意。第一个是训练时的 GT mask 坐标处理。BlendMask 的监督目标需要把 GT mask 从原图坐标映射到 RoI 坐标。如果这里直接采用整图裁出 RoI 再 resize的做法位置误差会被放大更稳妥的做法是先把 GT mask 通过 RoIAlign 相同的变换逻辑采样到目标尺寸保证训练和推理的坐标系完全一致。我自己一开始图省事用了前者mask AP 掉了接近 1 个点。第二个是推理时的 mask 阈值。默认的 mask 二值化阈值是 0.5但在小目标多的场景里0.5 会把很多置信度在 0.4~0.5 之间的前景都过滤掉。可以针对自己的验证集做一个简单的阈值扫描有时候把阈值降到 0.35 能让小物体的 recall 明显上升代价是 precision 轻微下降。这种工程性的微调往往比换模型收益来得更快。6. BlendMask思路的后续影响与适用场景6.1 为什么说这个思路后劲足复盘整个方法我觉得 BlendMask 最大的贡献不是某个惊艳的模块而是确立了一种实例级稀疏信息 语义级稠密信息 可微融合的范式。这个范式后来在很多视觉任务里都能看到影子全景分割里用实例 query 结合语义 logits视频分割里用 attention 聚合时序特征边缘检测里用全局先验加局部细化。理解 BlendMask 之后再看这些工作会觉得很多设计都是熟悉的。从训练角度讲这种拆分解也更好优化。直接回归一张 RoI mask网络必须同时学会实例在哪里和边缘长什么样而 BlendMask 把这两个问题拆给两个分支每个分支的任务都足够简单更容易收敛也更容易针对性地加改进。6.2 工程落地建议如果你的项目需要实时实例分割我建议直接拿 BlendMask 当起点按自己的场景做三件小事第一根据目标尺度调整 base map 的 stride。检测小目标就坚持 stride 8检测大目标且对速度要求高可以放宽到 stride 16。第二把 attention 的分辨率从 7×7 提升到 14×14同时把 C_a 从 8 提到 16。这个改动只影响 attention 分支不影响 bottom 分支和检测头实测 mask AP 有稳定提升代价是推理变慢 5% 左右显存变多 10% 左右。第三打开混合精度训练并把推理时的 mask 阈值放到验证集上重新扫一遍。这两步基本不花人力成本但能在不掉精度的情况下明显改善速度。6.3 什么时候别选 BlendMask话说回来BlendMask 也不是万能的。如果你的核心痛点是 mask 边缘的精细度比如医学影像里的组织轮廓分割那 1/8 stride 的 base map 本身就是一个瓶颈再好的融合逻辑也变不出高分辨率信息。这种场景更适合带边界监督的 refine 结构或者直接上 transformer 类的 mask 解码器。另外如果目标本身非常小比如遥感图像里的车辆和船只1/8 stride 甚至 1/4 stride 都可能不够。这种场景需要的是更高分辨率的输入和多尺度特征的强融合BlendMask 的 bottom 分支需要相应扩展否则小目标的 mask 会糊成一片。最后说一点个人体会。BlendMask 在 2020 年那批实例分割工作里算是非常克制的一个没有堆模块没有炫技结构简单到可以在半天内复现清楚。但也正是因为简单它的每个设计决策都经得起推敲值得一记。如果你正打算深入了解实例分割的模块化设计建议把 BlendMask 的源码一行一行读一遍再动手改其中一个分支试试效果收获会比单纯跑通官方代码大得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑