• 视频目标语义分割自动标注——从图像轮廓提取到转成json标签文件


    前言

    语义分割数据标注是为训练语义分割模型准备数据的过程。语义分割是计算机视觉领域的任务,其中需要为图像中的每个像素分配一个类别标签,以区分不同的对象或区域。标注数据时,通常需要为每个对象或区域分配一个唯一的标签,并创建与图像像素相对应的分割掩码。掩码是二进制图像,其中像素值指示每个像素属于哪个类别。例如,对于背景、人、车辆等类别,分别创建不同的掩码。

    手动标注工具:
    图像标注软件:您可以使用专门的图像标注工具,如LabelImg、Labelbox、VGG Image Annotator (VIA)、CVAT等,来手动绘制区域并分配标签。
    绘图工具:也可以使用一般绘图工具,如Adobe Photoshop或GIMP,手动绘制区域并创建掩码。

    半自动标注工具:
    GrabCut算法:这是一种基于交互式图像分割的方法,可以帮助快速生成分割掩码。
    超像素分割工具:使用工具如SLIC或QuickShift可以生成超像素,然后手动分配标签给不同的超像素区域。

    深度学习自动标注:
    分割模型辅助标注:可以使用预训练的语义分割模型,如Mask R-CNN、U-Net等,来辅助标注。这些模型可以自动提供初始分割结果,然后可以进行必要的微调。

    图像语义分割数据标注是一项费时费力的工作,特别是对视频中的目标进行语义分割标注时,要对视频进行拆帧之后对每一帧的里面所需要的目标进行标注,是一项繁琐又费时费力的工作。但随着Segment Anything与​Segment-and-Track Anything算法的出现,让分割标注任务不在那么麻烦,​Segment-and-Track Anything可以对视频里面的目标进行追踪之后,再分割,然后我们可以借助​Segment-and-Track Anything分割出来的mask自动生成标签文件。

    一、​Segment-and-Track Anything目标追踪与目标分割

    1.算法简介

    Meta AI的SAM)模型展现了强大的图像分割能力,但在处理视频数据方面存在一些挑战。Segment-and-Track Anything是由SAM模型扩展而来,使其能够支持视频数据的分割和跟踪。这一创新使SAM不仅能够分割图像中的对象,还能够跟踪它们随时间的变化。这一功能的应用潜力广泛,涵盖了各种时空场景,包括但不限于街景、增强现实、细胞图像分析、动画制作和航拍视频。

    在SAM-Track项目中,SAM模型在单卡上实现了强大的目标分割和跟踪能力。它具备处理大规模数据的潜力,能够同时追踪超过200个物体,为用户提供了卓越的视频编辑能力。
    在这里插入图片描述

    2.算法应用部署

    算法应用与部署可以看我之前的博客 :​Segment-and-Track Anything——通用智能视频分割、目标追踪、编辑算法解读与源码部署

    3.运动目标追踪与分割

    首先对视频第一帧进行目标分割,然后使用Segment-and-Track Anything进行整个视频的目标追踪与分割。
    在这里插入图片描述
    分割之后的结果如下:
    在这里插入图片描述

    二、生成标签

    1.语义分割标签格式

    要生成语义分割的标签,要了解语义分割的json文件的格式,这里使用labelme标注json文件进行举例,标注的标签文件如下:

    {
      "version": "0.2.4",
      "flags": {},
      "shapes": [
        {
          "label": "mat",
          "text": "",
          "points": [
            [
              234.0,
              248.0
            ],
            [
              229.0,
              246.0
            ],
            [
              207.0,
              247.0
            ]
          ],
          "group_id": null,
          "shape_type": "polygon",
          "flags": {}
        },
        {
          "label": "mat",
          "text": "",
          "points": [
            [
              237.0,
              245.0
            ],
            [
              236.0,
              249.0
            ],
            [
              237.0,
              250.0
            ],
            [
              237.0,
              260.0
            ],
            [
              239.0,
              268.0
            ]
          ],
          "group_id": null,
          "shape_type": "polygon",
          "flags": {}
        }
      ],
      "imagePath": "b (14).jpg",
      "imageData": null,
      "imageHeight": 518,
      "imageWidth": 500
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    2.轮廓提取与多边形拟合

    要对轮廓进行提取,提取轮廓之后,要进行多边形拟合

    def approx_PolyDP(cv_src):
        cv_gray = cv2.cvtColor(cv_src, cv2.COLOR_BGR2GRAY)
        cv_ret, cv_binary = cv2.threshold(cv_gray, 0, 255, cv2.THRESH_BINARY)
        contours, hierarchy = cv2.findContours(cv_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
        approxs = []
        for contour in contours:
            # 对轮廓进行多边形拟合
            # epsilon = 0.04 * cv2.arcLength(contour, True)
            approx = cv2.approxPolyDP(contour, 1, True)
            approxs.append(approx)
    
        return approxs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    3.生成标签文件

    多边形拟合之后,创建json文件

    def create_node(label_name,points):
        shape = {
            "label": label_name,
            "text": "",
            "points":
               points
            ,
            "group_id": None,
            "shape_type": "polygon",
            "flags": {}
        }
    
        return shape
    
    def create_json(img_name,img_w,img_h):
        name, _ = os.path.splitext(img_name)
        data = {
            "version": "0.2.4",
            "flags": {},
            "shapes": [
            ],
            "imagePath": img_name,
            "imageData": None,
            "imageHeight":img_h,
            "imageWidth": img_w
        }
    
        json_name = name + ".json"
    
        with open(json_name, "w") as json_file:
            json.dump(data, json_file, indent=4)
    
    def add_shape(json_name,node):
        with open(json_name, "r") as json_file:
            data = json.load(json_file)
    
        data["shapes"].append(node)
    
        # 保存更新后的JSON数据
        with open(json_name, "w") as json_file:
            json.dump(data, json_file, indent=4)
    
    def contour_to_json(img_name):
        cv_src = cv2.imread(img_name)
        approxs= approx_PolyDP(cv_src)
        height, width = cv_src.shape[:2]
    
        points_all = []
        if len(approxs) >= 1:
            for approx in approxs:
                points = []
                for i in range(len(approx)):
                    points.append([int(approx[i][0][0]), int(approx[i][0][1])])
            #         j = i + 1
            #         if j == len(approx):
            #              j = 0
            #         cv2.line(cv_src, (approx[i][0][0], approx[i][0][1]),
            #                   (approx[j][0][0], approx[j][0][1]), (255, 0, 0), 1)
            #     points_all.append(points)
            #
            # cv2.namedWindow("src",0)
            # cv2.imshow("src",cv_src);
            # cv2.waitKey()
    
            create_json(img_name,width,height)
    
            nodes = []
    
            for p in points_all:
                node = create_node("foot",p)
                nodes.append(node)
    
            name, _ = os.path.splitext(img_name)
            json_name = name + ".json"
            # add_shape(json_name,nodes[0])
            for n in nodes:
                add_shape(json_name,n)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    4.验证标签文件

    使用标注工具,如labelme打开,效果如下,代表测试可以:
    在这里插入图片描述

  • 相关阅读:
    记Windows的一个存在了十多年的bug
    ElementUI浅尝辄止31:Tabs 标签页
    【动态规划】按位与最大的最长子数组
    软件测试经验盘点:测试人的至暗时刻&高光时刻
    YOLOv8改进 | EIoU、SIoU、WIoU、DIoU、FocusIoU等二十余种损失函数
    Prometheus 四种metric类型
    Kafka与MySQL的组合使用
    快收下这份照片模糊变清晰方法攻略
    深圳考生注意!取得信息系统项目管理师证书还可以享受这些福利!
    NLP基本业务范围
  • 原文地址:https://blog.csdn.net/matt45m/article/details/133851280