使用EasyCV Mask2Former轻松实现图像分割
简介: EasyCV可以轻松预测图像的分割谱以及训练定制化的分割模型。本文主要介绍如何使用EasyCV实现实例分割、全景分割和语义分割,及相关算法思想。
作者:贺弘 谦言 临在
导言
图像分割(Image Segmentation)是指对图片进行像素级的分类,根据分类粒度的不同可以分为语义分割(Semantic Segmentation)、实例分割(Instance Segmentation)、全景分割(Panoptic Segmentation)三类。图像分割是计算机视觉中的主要研究方向之一,在医学图像分析、自动驾驶、视频监控、增强现实、图像压缩等领域有重要的应用价值。我们在EasyCV框架中对这三类分割SOTA算法进行了集成,并提供了相关模型权重。通过EasyCV可以轻松预测图像的分割谱以及训练定制化的分割模型。本文主要介绍如何使用EasyCV实现实例分割、全景分割和语义分割,及相关算法思想。
使用EasyCV预测分割图
EasyCV提供了在coco数据集上训练的实例分割模型和全景分割模型以及在ADE20K上训练的语义分割模型,参考EasyCV quick start(https://github.com/alibaba/EasyCV/blob/master/docs/source/quick_start.md)完成依赖环境的配置后,可以直接使用这些模型完成对图像的分割谱预测,相关模型链接在reference中给出。
实例分割预测
由于该示例中的mask2fromer算法使用了Deformable attention (在DETR系列算法中使用该算子可以有效提升算法收敛速度和计算效率),需要额外对该算子进行编译
cd thirdparty/deformable_attention
python setup.py build install
通过Mask2formerPredictor预测图像实例分割图
import cv2
from easycv.predictors.segmentation import Mask2formerPredictor predictor = Mask2formerPredictor(model_path='mask2former_instance_export.pth',task_mode='instance')
img = cv2.imread('000000123213.jpg')
predict_out = predictor(['000000123213.jpg'])
instance_img = predictor.show_instance(img, **predict_out[0])
cv2.imwrite('instance_out.jpg',instance_img)
输出结果如下图:
全景分割预测
通过Mask2formerPredictor预测图像全景分割图
import cv2
from easycv.predictors.segmentation import Mask2formerPredictor predictor = Mask2formerPredictor(model_path='mask2former_pan_export.pth',task_mode='panoptic')
img = cv2.imread('000000123213.jpg')
predict_out = predictor(['000000123213.jpg'])
pan_img = predictor.show_panoptic(img, **predict_out[0])
cv2.imwrite('pan_out.jpg',pan_img)
输出结果如下图:
语义分割预测
通过Mask2formerPredictor预测图像语义分割图
import cv2
from easycv.predictors.segmentation import Mask2formerPredictor predictor = Mask2formerPredictor(model_path='mask2former_semantic_export.pth',task_mode='semantic')
img = cv2.imread('000000123213.jpg')
predict_out = predictor(['000000123213.jpg'])
semantic_img = predictor.show_panoptic(img, **predict_out[0])
cv2.imwrite('semantic_out.jpg',semantic_img)
示例图片来源:cocodataset
在阿里云机器学习平台PAI上使用Mask2Former模型
PAI-DSW(Data Science Workshop)是阿里云机器学习平台PAI开发的云上IDE,面向各类开发者,提供了交互式的编程环境。在DSW Gallery中(链接),提供了各种Notebook示例,方便用户轻松上手DSW,搭建各种机器学习应用。我们也在DSW Gallery中上架了Mask2Former进行图像分割的Sample Notebook(见下图),欢迎大家体验!
Mask2Former算法解读
上述例子中采用的模型是基于Mask2former实现的,Mask2former是一个统一的分割架构,能够同时进行语义分割、实例分割以及全景分割,并且取得SOTA的结果,在COCO数据集上全景分割精度57.8 PQ,实例分割精度达50.1 AP,在ADE20K数据集上语义分割精度达57.7 mIoU。
核心思想
Mask2Former采用mask classification的形式来进行分割,即通过模型去预测一组二值mask再组合成最终的分割图。每个二值mask可以代表类别或实例,就可以实现语义分割、实例分割等不同的分割任务。
在mask classsification任务中,一个比较核心的问题是如何去找到一个好的形式学习二值Mask。如先前的工作 Mask R-CNN通过bounding boxes来限制特征区域,在区域内预测各自的分割谱。这种方式也导致Mask R-CNN只能进行实例分割。Mask2Former参考DETR的方式,通过一组固定数量的特征向量(object query)去表示二值Mask,通过Transformer Decoder进行解码去预测这一组Mask。(ps:关于DETR的解读可以参考:基于EasyCV复现DETR和DAB-DETR,Object Query的正确打开方式)
在DETR系列的算法中,有一个比较重要的缺陷是在Transformer Decoder中的cross attention中会对全局的特征进行处理,导致模型很难关注到真正想要关注的区域,会降低模型的收敛速度和最终的算法精度。对于这个问题Mask2former提出了Transformer Decoder with mask attention,每个Transformer Decoder block 会去预测一个attention mask并以0.5为阈值进行二值化,然后将这个attentino mask作为下一个block的输入,让attention模块计算时只关注在mask的前景部分。
模型结构
Mask2Former由三个部分组成:
- Backbone(ResNet、Swin Transformer)从图片中抽取低分辨率特征
- Pixel Decoder 从低分辩率特征中逐步进行上采样解码,获得从低分辨率到高分辨率的特征金字塔,循环的作为Transformer Decoder中V、K的输入。通过多尺度的特征来保证模型对不同尺度的目标的预测精度。
其中一层的Trasformer代码如下所示(ps:为了进一步加速模型的收敛速度,在Pixel Decoder中采用了Deformable attention模块):
class MSDeformAttnTransformerEncoderLayer(nn.Module): def __init__(self,
d_model=256,
d_ffn=1024,
dropout=0.1,
activation='relu',
n_levels=4,
n_heads=8,
n_points=4):
super().__init__() # self attention
self.self_attn = MSDeformAttn(d_model, n_levels, n_heads, n_points)
self.dropout1 = nn.Dropout(dropout)
self.norm1 = nn.LayerNorm(d_model) # ffn
self.linear1 = nn.Linear(d_model, d_ffn)
self.activation = _get_activation_fn(activation)
self.dropout2 = nn.Dropout(dropout)
self.linear2 = nn.Linear(d_ffn, d_model)
self.dropout3 = nn.Dropout(dropout)
self.norm2 = nn.LayerNorm(d_model) @staticmethod
def with_pos_embed(tensor, pos):
return tensor if pos is None else tensor + pos def forward_ffn(self, src):
src2 = self.linear2(self.dropout2(self.activation(self.linear1(src))))
src = src + self.dropout3(src2)
src = self.norm2(src)
return src def forward(self,
src,
pos,
reference_points,
spatial_shapes,
level_start_index,
padding_mask=None):
# self attention
src2 = self.self_attn(
self.with_pos_embed(src, pos), reference_points, src,
spatial_shapes, level_start_index, padding_mask)
src = src + self.dropout1(src2)
src = self.norm1(src) # ffn
src = self.forward_ffn(src) return src
- Transformer Decoder with mask attention 通过Object query和Pixel Decoder中得到的Multi-scale feature去逐层去refine二值mask图,得到最终的结果。
其中核心的mask cross attention,会将前一层的预测的mask作为MultiheadAttention的atten_mask输入,以此来将注意力的计算限制在这个query关注的前景中。具体实现代码如下:
class CrossAttentionLayer(nn.Module): def __init__(self,
d_model,
nhead,
dropout=0.0,
activation='relu',
normalize_before=False):
super().__init__()
self.multihead_attn = nn.MultiheadAttention(
d_model, nhead, dropout=dropout) self.norm = nn.LayerNorm(d_model)
self.dropout = nn.Dropout(dropout) self.activation = _get_activation_fn(activation)
self.normalize_before = normalize_before self._reset_parameters() def _reset_parameters(self):
for p in self.parameters():
if p.dim() > 1:
nn.init.xavier_uniform_(p) def with_pos_embed(self, tensor, pos: Optional[Tensor]):
return tensor if pos is None else tensor + pos def forward_post(self,
tgt,
memory,
memory_mask: Optional[Tensor] = None,
memory_key_padding_mask: Optional[Tensor] = None,
pos: Optional[Tensor] = None,
query_pos: Optional[Tensor] = None):
tgt2 = self.multihead_attn(
query=self.with_pos_embed(tgt, query_pos),
key=self.with_pos_embed(memory, pos),
value=memory,
attn_mask=memory_mask,
key_padding_mask=memory_key_padding_mask)[0]
tgt = tgt + self.dropout(tgt2)
tgt = self.norm(tgt) return tgt def forward_pre(self,
tgt,
memory,
memory_mask: Optional[Tensor] = None,
memory_key_padding_mask: Optional[Tensor] = None,
pos: Optional[Tensor] = None,
query_pos: Optional[Tensor] = None):
tgt2 = self.norm(tgt)
tgt2 = self.multihead_attn(
query=self.with_pos_embed(tgt2, query_pos),
key=self.with_pos_embed(memory, pos),
value=memory,
attn_mask=memory_mask,
key_padding_mask=memory_key_padding_mask)[0]
tgt = tgt + self.dropout(tgt2) return tgt def forward(self,
tgt,
memory,
memory_mask: Optional[Tensor] = None,
memory_key_padding_mask: Optional[Tensor] = None,
pos: Optional[Tensor] = None,
query_pos: Optional[Tensor] = None):
if self.normalize_before:
return self.forward_pre(tgt, memory, memory_mask,
memory_key_padding_mask, pos, query_pos)
return self.forward_post(tgt, memory, memory_mask,
memory_key_padding_mask, pos, query_pos)
Tricks
1.efficient multi-scale strategy
在pixel decoder中会解码得到尺度为原图1/32、1/16、1/8的特征金字塔依次作为对应transformer decoder block的K、V的输入。参照deformable detr的做法,对每个输入都加上了sinusoidal positional embedding和learnable scale-level embedding。按分辨率从低到高的循序依次输入,并循环L次。
2.PointRend
通过PointRend的方式来节省训练过程中的内存消耗,主要体现在两个部分a.在使用匈牙利算法匹配预测mask和真值标签时,通过均匀采样的K个点集代替完整的mask图来计算match cost b.在计算损失时按照importance sampling策略采样的K个点集代替完整的mask图来计算loss(ps实验证明基于pointreind方式来计算损失能够有效提升模型精度)
3.Optimization improvements
- 更换了self-attention和cross-attention的顺序。self-attention->cross-attention变成cross-attention->self-attention。
- 让query变成可学习的参数。让query进行监督学习可以起到类似region proposal的作用。通过实验可以证明可学习的query可以产生mask proposal。
- 去掉了transformer deocder中的dropout操作。通过实验发现这个操作会降低精度。
复现精度
实例分割及全景分割在COCO上的复现精度,实验在单机8卡A100环境下进行(ps :关于实例分割复现精度问题在官方repo issue 46中有提及)
Model |
PQ |
Box mAP |
Mask mAP |
memory |
train_time |
mask2former_r50_instance_official |
43.7 |
||||
mask2former_r50_8xb2_epoch50_instance |
46.09 |
43.26 |
13G |
3day2h |
|
mask2former_r50_panoptic_official |
51.9 |
41.7 |
|||
mask2former_r50_8xb2_epoch50_panoptic |
51.64 |
44.81 |
41.88 |
13G |
3day4h |
语义分割在ADE20K数据集上进行复现
Model |
mIoU |
train memory |
train_time |
mask2former_r50_semantic_official |
47.2 |
||
mask2former_r50_8xb2_e127_samantic |
47.03 |
5.6G |
15h35m |
使用EasyCV训练分割模型
对于特定场景的分割,可以使用EasyCV框架和相应数据训练定制化的分割模型。这里以实例分割为例子,介绍训练流程。
一、数据准备
目前EasyCV支持COCO形式的数据格式,我们提供了示例COCO数据用于快速走通流程。
wget http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/small_coco_demo/small_coco_demo.tar.gz && tar -zxf small_coco_demo.tar.gz mkdir -p data/ && mv small_coco_demo data/coco
二、模型训练
在EasyCV的config文件夹下,我们提供了mask2former的数据处理和模型训练及验证的配置文件(configs/segmentation/mask2former/mask2former_r50_8xb2_e50_instance.py),根据需要修改预测的类别、数据路径。
执行训练命令,如下所示:
#单机八卡
python -m torch.distributed.launch --nproc_per_node=8 --master_port 11111 tools/train.py \
configs/segmentation/mask2former/mask2former_r50_8xb2_e50_instance.py \
--launcher pytorch \
--work_dir experiments/mask2former_instance \
--fp16
模型导出,将config文件保存到模型中,以便在predictor中得到模型和数据处理的配置,导出后的模型就可直接用于分割图的预测。
python tools/export.py configs/segmentation/mask2former/mask2former_r50_8xb2_e50_instance.py epoch_50.pth mask2former_instance_export.pth
Reference
EasyCV往期分享
EasyCV开源地址:https://github.com/alibaba/EasyCV
EasyCV DataHub 提供多领域视觉数据集下载,助力模型生产 https://zhuanlan.zhihu.com/p/572593950
EasyCV带你复现更好更快的自监督算法-FastConvMAE https://zhuanlan.zhihu.com/p/566988235
基于EasyCV复现DETR和DAB-DETR,Object Query的正确打开方式 https://zhuanlan.zhihu.com/p/543129581
基于EasyCV复现ViTDet:单层特征超越FPN https://zhuanlan.zhihu.com/p/528733299
MAE自监督算法介绍和基于EasyCV的复现 https://zhuanlan.zhihu.com/p/515859470
EasyCV开源|开箱即用的视觉自监督+Transformer算法库 https://zhuanlan.zhihu.com/p/50521999
END
EasyCV会持续进行SOTA论文复现进行系列的工作介绍,欢迎大家关注和使用,欢迎大家各种维度的反馈和改进建议以及技术讨论,同时我们十分欢迎和期待对开源社区建设感兴趣的同行一起参与共建。
原文链接:https://click.aliyun.com/m/1000364647/
本文为阿里云原创内容,未经允许不得转载。
使用EasyCV Mask2Former轻松实现图像分割的更多相关文章
- 通用图像分割任务- 使用 Mask2Former 和 OneFormer
本文介绍两个领先的图像分割神经网络模型: Mask2Former 和 OneFormer.相关模型已经在 Transformers 提供. Transformers 是一个开源库,提供了很多便捷的先进 ...
- 盘它!基于CANN的辅助驾驶AI实战案例,轻松搞定车辆检测和车距计算!
摘要:基于昇腾AI异构计算架构CANN(Compute Architecture for Neural Networks)的简易版辅助驾驶AI应用,具备车辆检测.车距计算等基本功能,作为辅助驾驶入门级 ...
- HTML5轻松实现搜索框提示文字点击消失---及placeholder颜色的设置
在做搜索框的时候无意间发现html5的input里有个placeholder属性能轻松实现提示文字点击消失功能,之前还傻傻的在用js来实现类似功能... 示例 <form action=&quo ...
- 易用BPM时代,企业如何轻松驾驭H3?
众所周知,BPM作为企业发展的推动力,能敏捷高效的融合业务流程和信息资源.通过综合考虑流程的成本.效率.质量等方面因素,用IT系统将调整后的流程固化下来,从而降低企业管理成本,提高内部运营效率,提升企 ...
- 支付宝AR抢红包?前端轻松就破解~
近期阿里搞了各LBS+AR实景的红包玩法,小伙伴们在公司里都玩疯了~ 有时候为了抢一个红包,会跑到另一个地方去拍照,虽然略麻烦,但整体的互动还是很有意思的. 不过对于机智的前端童鞋来说,只需要简单的一 ...
- Java 8函数编程轻松入门(三)默认方法详解(default function)
default出现的原因 Java 8中对API最大的改变在于集合类,Java在持续演进,但是它一直保持着向后兼容. 在Java 8中为Collection接口增加了stream方法,这意味着所有实现 ...
- Android Studio快捷键switch case 轻松转换为if else
Android Studio快捷键switch case 轻松转换为if else 今天碰到的问题,没有找到资料,后面找到了方法,这个记下来,转载请注明出处:http://www.cnblogs.co ...
- owner:轻松管理java项目配置
前段时间,一同事说在 github 上“活捉了”一个很有趣的开源项目,它是一个超轻量级的 jar 包,能够帮助你在 java 项目中摒弃样板式的 properties 配置代码,让你轻松自如地管理和使 ...
- CSS3 Flexbox轻松实现元素的水平居中和垂直居中
CSS3 Flexbox轻松实现元素的水平居中和垂直居中 网上有很多关于Flex的教程,对于Flex的叫法也不一,有的叫Flexbox,有的叫Flex,其实这两种叫法都没有错,只是Flexbox旧一点 ...
- 30多条mysql数据库优化方法,千万级数据库记录查询轻松解决(转载)
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
随机推荐
- 基于2.4G私有协议的无线取餐系统设及实现
前记 最近在使用TLSR8355做几个小产品.正好赶上有客户需要一个无线取餐系统解决方案.笔者分析了一下需求.该芯片有充足的按键,LED灯,GPIO接口等.做这一款产品是顺道的事情. 需求梳理 功 ...
- 【stars-one】JetBrains产品试用重置工具
原文[stars-one]JetBrains产品试用重置工具 | Stars-One的杂货小窝 一款可重置JetBrains全家桶产品的试用时间的小工具,与其全网去找激活码,还不如每个月自己手动重置试 ...
- x86架构的内存溢出攻击原理演示(加强对计算机运行原理的理解,说明内存溢出的危害)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- [剑指 Offer II 114. 外星文字典] 拓扑排序
import java.util.*; class Solution { public static void main(String[] args) { Solution solution = ne ...
- UE虚幻引擎:生成云平台指定路径下的EXE文件
市面上大量优秀的游戏都是基于UE制作的,UE虚幻引擎制作的作品可以在windows.mac.linux以及ps4.x-boxone.ios.android甚至是html5等平台上运行.本文介绍了UE虚 ...
- clickhouse使用心得
clickhouse目前用在实时BI后台,只要数据稳定落库了,出报表很快,临时查询也很快,在使用过程中,对它的一些优点和不足也是深有体会,这里总结一下,不能做到面面俱到,但尽可能详细的介绍实际应用需要 ...
- golang sync.Map之如何设计一个并发安全的读写结构?
在 golang中,想要并发安全的操作map,可以使用sync.Map结构,sync.Map 是一个适合读多写少的数据结构,今天我们来看看它的设计思想,来看看为什么说它适合读多写少的场景. 如下,是g ...
- Python简单程序设计(计算程序设计(存款利息)篇)
如题: 解题方式如下:
- 用了两周开源堡垒机OneTerm,我有一些建议
上一篇文章分享了一款简洁且强大的开源堡垒机OneTerm,功能完善,代码简单,GO语言开发,用来学习很合适,拿来自用也没问题.堡垒机该有的核心功能基本都有了,方便与自有系统集成,我使用了两周,功能上没 ...
- C# Mat Bitmap互转
var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(source);//bitmap转mat Cv2.CvtColor(mat, mat, C ...