Segment Anything--SAM自动标注(一)

news2025/1/23 3:08:29

文章目录

  • 开场白
  • 基本组件
  • 搞事情从来不是一帆风顺
      • 复旦方案分支
      • 回归主线

开场白

  • 老样子先说一下为什么我会看到这篇文章。答案是“自动标注”。

  • 这个事情是这样,自动驾驶不光需要做目标检测任务也需要语义分割的信息给到后处理。当然现在做自动驾驶都在往BEV方案上靠了,但是传统的后融合方案还是有在做的。所以我们需要对一些目标检测和语义分割模型进行训练,就我知道的几家公司还是用yolo5或者其他版本,主要还是yolo,transformer当然也在搞。要训练神经网络就需要对训练的数据进行标注但是标注成本实在是太高了,对大公司来说直接劳动力密集型覆盖当然没什么问题,但是中小公司标注还是很慢的没法满足训练快速迭代的需要,所以就有了自动标注。我们用一个专门用来做语义分割的超大模型对现有标注好的数据进行训练,再用它对未标注数据进行预测生产伪标注。这个预测要求结果尽可能真实,最好和人工标注相差无异,理想是美好的,现实其实稍微差一点也可以接受。用人工标注的真实标签和大模型生成的伪标签来训练一个可以在车上跑的小模型,有提升就可以了。

  • 然后恰好,前段时间的分割一切(segment anything)的模型出来以后非常热,那我们当然也要搞一搞。然后不出意外就会遇到很多问题。比如prompt怎么给,分割效果怎么样,怎么才能将模型特性和我们的需求比较好的结合等等。

基本组件

在这里插入图片描述

https://arxiv.org/pdf/2304.02643.pdf 这文章并不是说做了一个什么样的模型,而是一个项目,如上图C,通过标注数据,训练模型,然后又通过模型生成标注数据,不断迭代。最后的成果模型是一方面,另外还有一个数据集。后面模型,数据,都会单独出来讲。这篇主要说一下在搞SAM的过程中遇到的坑。

搞事情从来不是一帆风顺

首先,如果要搞自动标注要面对的第一个问题是,SAM的输出结果并没有语义信息,这是最要紧的,当然我花了一些时间去找paper看别人是怎么做的。稍微放出来一些;

  1. https://github.com/Curt-Park/segment-anything-with-clip .走sam加clip路线,在sam的文章里面有说prompt可以给文本信息,但是并没有把代码放出来不过还是有人做了尝试
  2. https://github.com/fudan-zvg/Semantic-Segment-Anything ,复旦的语义sam,但也只是一个demo
    在这里插入图片描述
    OK。路线有了现在就是走哪一条的问题,基于我现有的资源和个人技能,选择第二条。
    我们有现成的语义分割模型,虽然训练数据不够效果差一些,但是做为语义来赋值应该还是可以的。

复旦方案分支

说到这了那就顺便来看一下这个投票模块。下面就是所谓“Semantic voting module",原理很简单,先对mask面积进行排序,然后遍历mask为有效值取出语义部分,如果语义部分只有一类那就赋值类别,如果不是那就按mask对应面积的最大语义来赋值,精髓torch.bincount(propose_classes_ids.flatten()).topk(1).indices
没什么好说的。oneformer,segformer后面有空再说。

def semantic_segment_anything_inference(filename, output_path, rank, img=None, save_img=False,
                                 semantic_branch_processor=None,
                                 semantic_branch_model=None,
                                 mask_branch_model=None,
                                 dataset=None,
                                 id2label=None,
                                 model='segformer'):

    anns = {'annotations': mask_branch_model.generate(img)}
    h, w, _ = img.shape
    class_names = []
    if model == 'oneformer':
        class_ids = oneformer_func[dataset](Image.fromarray(img), semantic_branch_processor,
                                                                        semantic_branch_model, rank)
    elif model == 'segformer':
        class_ids = segformer_func(img, semantic_branch_processor, semantic_branch_model, rank)
    else:
        raise NotImplementedError()
    semantc_mask = class_ids.clone()
    anns['annotations'] = sorted(anns['annotations'], key=lambda x: x['area'], reverse=True)
    for ann in anns['annotations']:
        valid_mask = torch.tensor(maskUtils.decode(ann['segmentation'])).bool()
        # get the class ids of the valid pixels
        propose_classes_ids = class_ids[valid_mask]
        num_class_proposals = len(torch.unique(propose_classes_ids))
        if num_class_proposals == 1:
            semantc_mask[valid_mask] = propose_classes_ids[0]
            ann['class_name'] = id2label['id2label'][str(propose_classes_ids[0].item())]
            ann['class_proposals'] = id2label['id2label'][str(propose_classes_ids[0].item())]
            class_names.append(ann['class_name'])
            # bitmasks.append(maskUtils.decode(ann['segmentation']))
            continue
        top_1_propose_class_ids = torch.bincount(propose_classes_ids.flatten()).topk(1).indices
        top_1_propose_class_names = [id2label['id2label'][str(class_id.item())] for class_id in top_1_propose_class_ids]

        semantc_mask[valid_mask] = top_1_propose_class_ids
        ann['class_name'] = top_1_propose_class_names[0]
        ann['class_proposals'] = top_1_propose_class_names[0]
        class_names.append(ann['class_name'])
        # bitmasks.append(maskUtils.decode(ann['segmentation']))

        del valid_mask
        del propose_classes_ids
        del num_class_proposals
        del top_1_propose_class_ids
        del top_1_propose_class_names
    
    sematic_class_in_img = torch.unique(semantc_mask)
    semantic_bitmasks, semantic_class_names = [], []

    # semantic prediction
    anns['semantic_mask'] = {}
    for i in range(len(sematic_class_in_img)):
        class_name = id2label['id2label'][str(sematic_class_in_img[i].item())]
        class_mask = semantc_mask == sematic_class_in_img[i]
        class_mask = class_mask.cpu().numpy().astype(np.uint8)
        semantic_class_names.append(class_name)
        semantic_bitmasks.append(class_mask)
        anns['semantic_mask'][str(sematic_class_in_img[i].item())] = maskUtils.encode(np.array((semantc_mask == sematic_class_in_img[i]).cpu().numpy(), order='F', dtype=np.uint8))
        anns['semantic_mask'][str(sematic_class_in_img[i].item())]['counts'] = anns['semantic_mask'][str(sematic_class_in_img[i].item())]['counts'].decode('utf-8')

回归主线

方案也确定了,如果事情可以按着原来的方案走就好啦。现实的情况是,SAM的分割效果并不完美。

  1. 如果以随机撒点的形式也就是”SamAutomaticMaskGenerator生成的mask是不受控制的,并且在边界上存在空隙和空洞,这也是paper里面有提到的。在这里插入图片描述
    当这些空隙和空洞遇到不那么准确的语义分割就会导致一团糟。
  2. 如果想要尽可能少的空隙和空洞,有对sam的prompt输入尝试过修改, 但效果也并不会好。并且SAM虽然在paper中提及,Prompt的输入形式可以是点、框、掩码、文本。但现实是只有点和框是可用的,文本提示的代码没有放出,掩码输入并不会有什么作用(这个问题在官方的仓库中有很多人讨论,从代码上看掩码输入成为稠密编码以后直接加在了原图上)。
  3. 对于SAM存在的很多问题,如果真要着手去进行解决和适配,需要显卡资源也需要时间,但现在就是又缺时间又缺资源。也尝试过对SAM进行微调,github有同学搞过finetune-anything,以有监督的形式对SAM直接做修改和微调但这样做的话还不如直接更换其他专门用来做语义分割的模型,失去prompt encoder以后效果大降。

所以基于以上种种原因,SAM并不适合做全自动的标注,但是做一些半自动的辅助标注来说还是可以的,但辅助完的边界还是需要精修,得不偿失。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1289953.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IntelliJ IDEA 之初体验

文章目录 第一步:下载与安装 IntelliJ IDEA1)官网下载2)选择那种安装包3)开始下载4)解压 第二步:启动 IntelliJ IDEA第三步:创建第一个 Java 项目第四步:运行第一个 Java 程序1&…

【408】计算机学科专业基础 - 计算机组成原理

一、计算机系统概述 【复习提示】 本章是组成原理的概述,考查时易针对有关概念或性能指标出选择题,也可能综合后续章节的内容出有关性能分析的综合题。掌握本章的基本概念,是学好后续章节的基础。部分知识点在初学时理解不深刻也无须担忧&am…

智能优化算法应用:基于变色龙算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于变色龙算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于变色龙算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.变色龙算法4.实验参数设定5.算法结果6.参考文献7.…

十五、FreeRTOS之FreeRTOS信号量

本节需要掌握以下内容: 1,信号量的简介(了解) 2,二值信号量(熟悉) 3,二值信号量实验(掌握) 4,计数型信号量(熟悉) 5&…

Linux--程序地址空间

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 [TOC](文章目录) 一、程序地址空间回顾 我们在讲C语言的时候,老师给大家画过这样的空间布局…

Transformer在视觉的应用

文章目录 Vison TransformerSwin TransformerVisual Attention Network Vison Transformer transformer 在 cv 中最重要的算法 Linear Projection of Flattened Patches 对于标准的Transformer模块,要求输入的是token(向量)序列&#xff…

鸿蒙4.0开发笔记之ArkTS语法基础之应用生命周期与页面中组件的生命周期(十六)

文章目录 一、应用生命周期二、生命周期函数定义三、生命周期五函数练习 一、应用生命周期 1、定义 应用生命周期就是代表了一个HarmonyOS应用中所有页面从创建、开启到销毁等过程的全生命周期。查看路径如下: Project/entry/src/main/ets/entryability/EntryAbili…

vue elementUI 上传非空验证

<el-form-item label"照片" prop"staffImg"><template v-slot:label><span v-show"!rules.staffImg[0].required"style"color: #ff4949;margin-right: 4px;">*</span><span>照片</span></temp…

【JavaWeb学习笔记】6 - Tomcat

项目代码 零、在线文档 Apache Tomcat 8 (8.0.53) - Documentation Index WEB开发 1. WEB,在英语中web表示网/网络资源(页面&#xff0c;图片,css,js)意思&#xff0c;它用于表示WEB服务器(主机)供浏览器访问的资源 2. WEB服务器(主机)上供外界访问的Web资源分为: 静态web…

LeetCode 每日一题 Day 4

2477. 到达首都的最少油耗 给你一棵 n 个节点的树&#xff08;一个无向、连通、无环图&#xff09;&#xff0c;每个节点表示一个城市&#xff0c;编号从 0 到 n - 1 &#xff0c;且恰好有 n - 1 条路。0 是首都。给你一个二维整数数组 roads &#xff0c;其中 roads[i] [ai,…

Myblog01-基于基本的javaWeb设计实现

目录 一、项目概述&#xff1a; 应用技术&#xff1a; 接口实现&#xff1a; 数据库建表&#xff0c;sql脚本&#xff1a; 页面展示&#xff1a;登陆页面 项目源码&#xff1a;myblog01: 初版的个人博客项目-使用基本的javaWeb (gitee.com) 二、对博客系统进行测试 总结 一、项…

怎么给文章润色?文章润色怎么收费?

文章润色&#xff0c;指的是在原有文章基础上&#xff0c;对语言表达、逻辑结构、风格等方面进行优化调整&#xff0c;以提高文章的阅读体验和质量。 润色不同于修改&#xff0c;修改主要针对文章中的错误&#xff0c;如语法、拼写、标点等&#xff1b;而润色则是对文章的整体…

网页抓取为什么要使用http代理?

目录 前言 一、网页抓取的定义 二、使用HTTP代理的原因 1. 防止IP被封锁 2. 提高访问速度 3. 保护隐私 4. 突破地域限制 三、使用Python进行网页抓取并使用HTTP代理 1. 安装必要的Python模块 3. 获取网页源代码 4. 解析网页内容 总结 前言 网页抓取是指从互联网中…

如何解决syntaxerror: more than 255 arguments 报错

如何解决syntaxerror: more than 255 arguments 报错 问题背景解释解决方案 问题背景 今天拼接特征的时候&#xff0c;突然代码报错syntaxerror: more than 255 arguments &#xff0c;看了一下感觉这个报错非常有意思&#xff0c;估计平时也是没机会碰到&#xff0c;和大家分…

课题学习(十五)----阅读《测斜仪旋转姿态测量信号处理方法》论文

一、 论文内容 1.1 摘要 为准确测量旋转钻井时的钻具姿态&#xff0c;提出了一种新的信号处理方法。测斜仪旋转时&#xff0c;垂直于其旋转轴方向加速度计的输出信号中重力加速度信号分量具有周期性特征&#xff0c;以及非周期性离心加速度分量频率低于重力加速度信号分量频率…

ROS-ROS通信机制-参数服务器

文章目录 一、基础理论知识二、C实现三、Python实现 一、基础理论知识 参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器&#xff0c;可以将数据存储在该容器中&#xff0c;被不同的节点调用&#xff0c;当然不同的节点…

【GAMES101】二维变换和齐次坐标

这几天都在抽空学OpenGL、敲leetcode和看games&#xff0c;这里留点笔记给以后复习 games101第一节课在吹水&#xff0c;第二节课讲了线性代数的入门知识&#xff0c;比较简单&#xff0c;这里稍微回顾一下重点&#xff0c;然后开始讲第三节课的二维变换和齐次坐标 目录 向量…

前端CSS(层叠样式表)总结

CSS2总结 一、CSS基础 1. CSS简介 CSS 的全称为&#xff1a;层叠样式表 ( Cascading Style Sheets ) 。CSS 也是一种标记语言&#xff0c;用于给 HTML 结构设置样式&#xff0c;例如&#xff1a;文字大小、颜色、元素宽高等等。 简单理解&#xff1a; CSS 可以美化…

一篇文章带你详细了解C++智能指针

一篇文章带你详细了解C智能指针 为什么要有智能指针内存泄漏1.什么是内存泄漏&#xff0c;它的危害是什么2.内存泄漏的分类3.如何避免内存泄漏 智能指针的使用及原理1.RAII2.智能指针的原理3.auto_ptr4.unique_ptr5.shared_ptr6.weak_ptr 为什么要有智能指针 C引入智能指针的主…