图像分割——常用数据和算法
概念video instance segmentation (VIS)把实例分割出来video semantic segmentation (VSS)只关心类别不关心实例video panoptic segmentation (VPS)实例和类别都关心Open Vocabulary在传统的计算机视觉任务中通常会有一个固定的标签集合即封闭词汇(ClosedVocabulary)。然而现实世界中的物体和场景是多样的难以用一个固定的标签集合来描述。为了应对这一挑战研究者们提出了开放词汇(Open Vocabulary)的概念。开放词汇指的是一种 可扩展的标签集合它允许计算机视觉系统在遇到 新的物体或场景 时能够 自我更新 并学习到新的标签。这种方法可以让计算机视觉系统更好地适应现实世界的多样性。数据开源数据这是TAO论文中列举的一些数据集在类别占比方面的差异数据集名称简介cocohttps://cocodataset.org/#homeCOCOCommon Objects in Context由微软团队于 2014 年创建用于训练和评估 AI 模型。覆盖 80 种常见物体类别如人、汽车、动物和 91 种材料类别如天空、墙壁对于分割任务mask使用Run Length Encoding (RLE) scheme编码提供API进行提取分成3种标注instancesstuffpanoptic。前面说的80类别是指instancesstaff是草地天空这种不可数没有instance概念的。所以coco2017数据集有三个标注文件captions_train2017.json描述的是每个image的license类型ulr宽度长度id拍摄时间等信息和图片是根据file_name对应的而不是顺序但其实instances_val2017.json也有这个信息在介绍完images之后才是annotations里面包含了segmentationbbox等信息person_keypoints_val2017.json多出的信息是keypoints。COCO 的keypoints就是一个[x, y, 可见性]的三元组重复 17 次拼成的长列表person_keypoints_val2017.json的images中的图片不一定有人也不一定有keypoints信息所以还是要以coco.getAnnIds结果为准Cityscapeshttps://www.cityscapes-dataset.com在 50 个城市的春季、夏季和秋季YouTube-VOSVideo Object Segmentation2019 versionTraining: 3471 videos, 65 categories and 6459 unique object instances.Validation: 507 videos, 65 training categories, 26 unseen categories and 1063 unique object instances.Test: 541 videos, 65 training categories, 29 unseen categories and 1092 unique object instances.LVIS (Large Vocabulary Instance Segmentation)https://github.com/FishYuLi/BalancedGroupSoftmaxFacebook AI Research (FAIR)针对针对长尾分布问题提出所以看起来分得很细使用COCO 2017的数据只是标注是新的。每个图对应的标注能有80多个ann_idsann_id因为全局唯一性为了避免和COCO冲突所以一般从5000开始编号标注采用和COCO一样的方法mask以多边形Polygon保存在json中使用lvis-api解码得到mask(pronounced ‘el-vis’)1203 个类别中有些只有几十个样本如 “snowmobile”而 “person” 有几十万个。person的类别id是793这是WordNet synset 字典序排序得到的不同于coco中person的类别id是1除了person还有person skiingperson riding a bike等类别互斥关系每个类别在json中都统计了出现image和instnce的次数还有同义词等categories: [{image_count: 8,synonyms: [aerosol_can,spray_can],def: a dispenser that holds a substance under pressure,id: 1,synset: aerosol.n.02,name: aerosol_can,frequency: c,instance_count: 11},lvis_v1_val.jsoncategories字段通常出现在文件开头lvis_v1_train.jsoncategories字段出现在文件末尾在庞大的annotations数组之后lvis LVIS(json_path)all_catslvis.cats 可以得到所有类别每个类别有frequency属性分为fcr三类表示frequentcommonrare出现image的频率https://docs.ultralytics.com/datasets/detect/lvis/https://www.lvisdataset.org/datasethttps://www.lvisdataset.orgTAO(Tracking Any Object)https://github.com/TAO-Dataset/tao/tree/master在multi-object tracking中对标COCO2,907段半分钟的视频833 categorieshttps://taodataset.org/?spm5176.28103460.0.0.18417551Y6B1XlMOTmulti object trackinghttps://motchallenge.net/data/MOT17/DAVISDensely Annotated VIdeo Segmentationhttps://davischallenge.org/?spm5176.28103460.0.0.18417551Y6B1Xl无类别只需要区分前景背景使用mmsegmentionmask 时序传播提供现成的mask图不同instance以颜色区分可以直接根据文件夹名字找到对应的类别/场景MPII Human Pose Dataset图片有12.9G标注是mat格式https://www.mpi-inf.mpg.de/departments/computer-vision-and-machine-learning/software-and-datasets/mpii-human-pose-dataset/download生成/标注工具MoMaskhttps://github.com/EricGuo5513/momask-codesWorldDreamerhttps://world-dreamer.github.ioQwen-Image-Layeredhttps://github.com/QwenLM/Qwen-Image-Layered/tree/main使用了VAE把RGB和RGBA统一起来使用Layer3D RoPE嵌入了layer索引信息渐进学习From Text-to-RGB to Text-to-RGBAText-to-RGBA to Text-to-Multi-RGBAText-to-Multi-RGBA to Image-to-Multi-RGBAGrounded SAMhttps://github.com/IDEA-Research/Grounded-Segment-AnythingSapienshttps://github.com/facebookresearch/sapiens?tabreadme-ov-fileX-AnyLabelinghttps://github.com/CVHub520/X-AnyLabeling支持多种任务典型的C/S (Client/Server) 架构设计服务器端集成了各种模型而客户端可以是多个并行标注。https://github.com/CVHub520/X-AnyLabeling/blob/main/docs/en/model_zoo.mddataset/X-anylabel/X-AnyLabeling-Server/configs/models.yaml 没有被注视掉的就是要使用的模型sam2.1_hiera_base_plus.ptSAM 2.1版本。它是 SAM 2 的升级版2024年底/2025年初发布主要改进了小物体检测精度、复杂场景下的分割稳定性以及视频跟踪的长时记忆能力。相比 SAM 2它修复了很多边缘情况的 Bug。hiera:代表骨干网络架构使用的是HiViT (Hierarchical Vision Transformer)。图像分割算法maskRCNNhttps://wiki.math.uwaterloo.ca/statwiki/index.php?titleMask_RCNN2018年的文章也是来自facebook FAIR团队第一作者hekaiming。https://arxiv.org/pdf/1703.06870在faster-RCNN基础上新增mask分支。RCNN1.选择性搜索Selective Search得到2k个目标的候选区域2.卷积神经网络CNN对每个区域进行特征提取3. SVM做分类regression回归得到bounding boxFast-RCNN1.选择性搜索Selective Search得到2k个目标的候选区域2.卷积神经网络CNN对整个图进行特征提取再取候选区域3. 特征图ROI Pooling共享池化支持不同大小4.FC同时完成分类和回归Faster-RCNN把Fast-RCNN的第一步改成使用区域提议网络RPN生成区域提议Mask-RCNN在Faster-RCNN最后增加一个mask branch用于分割DETR开启了transforme的时代2020年的文章End-to-End Object Detection with Transformershttps://arxiv.org/pdf/2005.12872https://github.com/facebookresearch/detr不需要anchor不需要非极大值抑制NMS。第一个使用transformer到2D检测中。直接二分匹配box。CNN提取的特征和位置编码一起被送入encoder然后是decoderFFNMaskformer2021年的文章Per-Pixel Classification is Not All You Need for Semantic Segmentationhttps://github.com/facebookresearch/MaskFormermaskformer的基本思想是把语义分割、实例分割用一个统一的框架、损失和训练过程来实现。Our key insight: mask classification is sufficiently general to solveboth semantic- and instance-level segmentation tasks in a unified manner usingthe exact same model, loss, and training procedure.以往都认为分割就是对每个像素做分类但是这篇文章就告诉我们没必要这样MaskFormer: Per-Pixel Classification is Not All You Need for Semantic Segmentation直接预测一系列的二值mask。per-pixel的方法每个pixel的位置使用相同的分类loss而mask的方法每个mask都有自己的per-pixel loss和per-mask loss。经过backbone之后分别进行pixel decoder和transformer decoder分别得到像素级别和mask级别的embeddings。因为要基于mask所以mask embedding和pixel embedding结合得到binary mask loss。Mask2FormerCVPR 2022https://github.com/facebookresearch/Mask2Former在Mask Transformer的基础上又引入了Masked-attention把cross-attention限制在预测的mask周围所以叫mask2former。结构上和maskForme差不多都是两个decoder不过对transformer decoder进行了修改增加了mask并且交换了self attention和cross attention的位置并且考虑到小物体所以把每层的pxiel decoder送入了不同层的transformer decoder中。SAMhttps://github.com/facebookresearch/segment-anything这是fecebook中更有名的分割算法作者中仍然可以看到之前maskformerDETRmask2former的作者Alexander Kirillov。SAM其实是构建了分割的一整个系统通过语言或者其他的prompt来指导模型去分割得到mask这些prompts可能是maskpointsboxtextheavy的encoder得到embedding之后利用这些prompt会得到对应的mask。参考代码dataset/Ground-SAM/segment-anything/notebooks/automatic_mask_generator_example.ipynbmasks mask_generator.generate(image)这里得到的masks是多个mask构成的list。每个mask除了mask本身外还有areabboxpredicted_iou等信息在dataset/Ground-SAM/segment-anything/scripts/amg.py 中会把每个mask都保存下来并且把这些属性保存在csv文件中。python scripts/amg.py --checkpoint /home/zcg2/workspace/segmention/dataset/Ground-SAM/segment-anything/sam_vit_h_4b8939.pth --model-type vit_h --input /home/zcg2/workspace/segmention/dataset/Ground-SAM/segment-anything/notebooks/images/dog.jpg --output ./outSapiens也是meta的一次性可以完成四个任务2D pose, part segmentation, depth, normal。也使用了OpenMMLab。BiRefNetBilateral Reference for High-Resolution Dichotomous Image Segmentationhttps://github.com/ZhengPeng7/BiRefNetCAAI AIR 2024阿里联合南开等高校开发的用于高分辨率二分图像分割dichotomous image segmentation (DIS)。分为两个部分localization module (LM) and the reconstruction module (RM)最左边是经典的Unet结构b是把图像金字塔作为输入c在b的基础上在decoder阶段也使用多尺度的图像。BIRefNet在c的基础上使用的仍然是原始scale的原图只不过切分成了patch利用from einops import rearrange并且使用了gradient priors由拉普里斯得到。使用四种loss从四个方面去约束modenethttps://github.com/ZHKKKe/MODNet?tabreadme-ov-file#data-preparationMODNet: Real-Time Trimap-Free Portrait Matting via Objective Decomposition (AAAI 2022)matting objective decomposition network 之前的要不是需要额外输入要不是多阶段的MODnet是第三种分了两个并行的分支分别是高分辨率和低分辨率的分别提取边缘和主体大致范围主要靠e-ASPP找到。再加上最后的融合所以MODNet 有三个branchSSemantic, Ddetail, and Ffusion计算三个输出sdalpha与真实值Ground Truth之间的误差总损失函数是三部分之和。也可以看作是内部的“语义分支”自我生成一个隐式的 Trimap 指引从而实现端到端的自动抠图。S分支只需要提取高层特征所以任何CNN结构都可以这里选择的是MobileNetV2最后一层sigmoid之后通道数为1。对应GT需要下采样16倍。为了解决空洞的问题需要使用ASPPAtrous Spatial Pyramid Pooling但是ASPP计算量大又使用了改进的e-ASPP把参数量和计算量减小到了1%。ASPP核心是ASPP通过并行使用不同膨胀率的空洞卷积e-ASPP则把空洞卷积也变成分离卷积并且提前使用1x1解决降低了通道数。因为需要平滑一点所以使用L2 loss。D分支同时使用了原始图像I还有S分支的最终特征还有S分支的低层特征。与S相比D使用更少的卷积12层卷积的通道数也更少最大通道数是64并且为了减少计算量也没一直保持原始的分辨率在第一层就降低分辨率为1/4在最后两层才恢复原来的分辨率。因为有skip link所以donwsample的影响可以忽略不计。这个分支使用L1 loss并且为了让它学习边缘所以通过膨胀腐蚀得到mask去加权L1 loss。F分支是CNN把S输出上采样后和D的输出concatenate然后得到最终的alpha输出。loss是L1 loss和compositional loss 的和。因为制作GT成本很高所以数据集都很小。普遍的做法是背景替换但有泛化性的问题。观察到在训练集中不同分支间一致性比较高在真实数据中一致性低所以提出sub-objectives consistency (SOC)自监督地提高了在真实数据中的泛化性本质是增强了三个输出之间的一致性alpha分别和s和d计算L2和L1损失。问题是s缺失细节容易把alpha也带偏所以计算SOC时需要固定模型参数M把SOC前后的M和M‘的d和d’的L1 loss作为正则项。训练中使用了合成数据,由前景和背景进行合成的数据集类似论文 Deep Image Matting 里使用的数据集Composition-1k。PPM100数据集PaddleSeg需要安装paddle千问说很多在线抠图工具的后端就是用的这个。对比MODNet, PP-MattingV2推理速度提升44.6% 误差平均相对减小17.91%。paddle可能对cuda支持不好这时候sigmoid失效导致出来的alpha有4条纹所以可以直接用cpu推理export CUDA_VISIBLE_DEVICEShttps://github.com/JSHZT/ppmattingv2_pytorch/blob/main/Matting/docs/quick_start_en.mdhttps://github.com/PaddlePaddle/PaddleSegDeep Image Mattinghttps://sites.google.com/view/deepimagemattingMGMattingMask Guided Matting via Progressive Refinement Networkhttps://github.com/yucornetto/MGMattingP3M-Nethttps://github.com/ViTAE-Transformer/p3m-nethttps://arxiv.org/pdf/2203.16828没有使用到trimap即便是HYBRID模式分了两次推理也只是img尺寸不一样第一次得到的概率图用于第二次的后处理而不是作为trimap送入网络中。视频分割算法MaskTrackRCNN2019年的文章第一个提出来做视频实例分割所以文章名字就叫Video Instance Segmentation。https://github.com/youtubevos/MaskTrackRCNN在maskRCNN基础上又新加了racking branch可以detect, segment, and track object instances构建了YouTube-VIS数据集。通过计算当前实例的特征与之前的实例的特征可以得到当前实例属于之前出现过的N种内的哪个类别或者是新出现的类别d需要安装mmdetection OpenMMLab 的目标检测工具箱:git clone https://github.com/open-mmlab/mmdetection.git cd mmdetection pip install -r requirements/build.txt # 安装编译依赖 pip install -v -e . # 开发模式安装MaXTronOpenAI等团队提出的视频分割技术https://github.com/TACJu/Axial-VSClip-level的一个clip就是由23帧组成的短视频。DVIShttps://github.com/KlingTeam/DVIS_PlusD是decoupling解藕成三部分segmentation使用Mask2Former, Referring Tracker, and Temporal Refiner和CLIP结合后又有了OV-DVIS需要安装detectron2Detectron2是Facebook AI Research的检测和分割框架其主要基于PyTorch实现但具有更模块化设计因此它是灵活且便于扩展的python -m pip install githttps://gitcode.com/GitHub_Trending/de/detectron2.git python -m pip install timm # timm 是一个由 Ross Wightman 开发的 PyTorch 库它提供了许多现代的图像分类模型旨在加速研究和开发PP-HumanSeg百度目前工业界在手机端人像分割的标杆MediaPipe Segmentation (Google)Zoom/Google Meet 里看到的背景虚化技术使用了图结构搜索 (NAS) 找到的最优架构CIRKDmodnetDiffusinMatmatteformerLabel_Assisted_Distillation-mainu2netmmdetctionloss1. Dice loss就是计算交并比def _DiceLoss(self, pred, gt): # [N, C, H, W] one-hot gt_fore gt[:,1,:,:] pred_fore pred[:,1,:,:] intersection (pred_fore * gt_fore).sum() pred_fore pred_fore.contiguous().view(-1) gt_fore gt_fore.contiguous().view(-1) dice_coeff (2. * intersection 1e-5) / (pred_fore.sum() gt_fore.sum() 1e-5) return 1 - dice_coeff2. 交叉熵看作分类当然可以使用交叉熵def _loss(self, true, pred): pred torch.maximum(torch.minimum(pred, torch.tensor(1 - 1e-15, dtypetorch.float32)), torch.tensor(1e-15, dtypetorch.float32)) softmax_loss -torch.sum(true * torch.log(pred), dim1) # [N, C, H, W] - [N, H, W] return softmax_loss # true是二通道的one-hot编码pred是softmax的输出3. 编译BCE对图像分割边缘计算BCEnn.BCELoss(reductionmean) 是 PyTorch 中专门用于二分类任务或每个像素做二分类的语义分割任务的损失函数。reductionmean 表示它会自动计算并返回当前批次batch中所有元素损失的平均值。BCELoss 内部会计算对数log它假设传入的 pred 已经经过了 Sigmoid 激活函数。如果你的网络最后一层输出的是原始分数Logits即没有经过 Sigmoid请直接改用 nn.BCEWithLogitsLoss。它不仅用法一样而且在数值计算上更加稳定。import torch import torch.nn as nn import torch.nn.functional as F class YourModel(nn.Module): def __init__(self): super().__init__() # 初始化 BCELossreductionmean 是默认值表示对 batch 内所有元素求平均 self.bce nn.BCELoss(reductionmean) def _boundaryBCE_loss(self, pred, gt): # 1. 提取前景通道保持在 GPU/CPU 上不要转 numpy # 使用 .detach() 是因为在生成边界 mask 时不需要梯度避免 inplace 操作报错 pred_fore pred[:, 1, :, :].detach() gt_fore gt[:, 1, :, :].detach() # 2. 二值化 (使用 PyTorch 原生操作) binary_pred (pred_fore 0.5).float() binary_gt (gt_fore 0).float() # 3. 模拟膨胀和腐蚀 (使用 PyTorch 的 max_pool2d 和 avg_pool2d) # 注意pooling 需要 [N, 1, H, W] 的输入所以要 unsqueeze(1) kernel_size 8 # 最大池化 膨胀 (Dilation) dilation_gt F.max_pool2d(binary_gt.unsqueeze(1), kernel_sizekernel_size, stride1, paddingkernel_size//2).squeeze(1) # 最小池化 腐蚀 (Erosion) # PyTorch 没有直接的 min_pool可以用 -max_pool(-x) 来巧妙实现 erode_pred -F.max_pool2d(-binary_pred.unsqueeze(1), kernel_sizekernel_size, stride1, paddingkernel_size//2).squeeze(1) erode_gt -F.max_pool2d(-binary_gt.unsqueeze(1), kernel_sizekernel_size, stride1, paddingkernel_size//2).squeeze(1) # 4. 提取边界宽度 boundary_width_pred (pred_fore - erode_pred) boundary_width_pred (boundary_width_pred 0).float() boundary_width_gt (dilation_gt - erode_gt) boundary_width_gt (boundary_width_gt 0).float() # 5. 生成边界区域的预测和真值 pred_boundary boundary_width_pred * pred_fore gt_boundary boundary_width_gt * gt_fore # 6. 计算 BCE 损失 (传入的必须是 float 类型的 Tensor) boundaryBCE_loss self.bce(pred_boundary, gt_boundary) return boundaryBCE_lossreference1.https://developer.volcengine.com/articles/74035698588368568432.https://cloud.tencent.com/developer/article/2490460