3D点云目标检测数据集标注工具 保姆级教程——CVAT (附json转kitti代码)

前言:
笔者尝试过很多3D标注软件都遇到很多问题,例如CloudCompare不适合做3D目标检测的数据集而且分割地面的时很繁琐;labelCloud没有三视图,视角难以调整标得不够精确;SUSTechPOINTS换帧麻烦、输出时存储在docker里面不方便。 CVAT是我这段时间用起来相当丝滑的一个3D目标检测的标注工具了,但是关于CVAT的3D标注教程很少,所以只能自己摸索,最后整理出了这篇教程手册供大家参考。

目录

  • 1. CVAT安装教程
  • 2. 3D点云标注详细流程
    • 2.1 创建3D点云标注任务(Task):
    • 2.2 指定任务的参数:
    • 2.3 数据集上传并进入任务job:
    • 2.4 标注说明:
      • 2.4.1. 可使用鼠标或键盘来改变视图:
      • 2.4.2. 使用长方体进行注释
        • 1)==使用shape方式进行批注(适合帧间目标不连续的情况)==
        • ==2)使用track方式进行批注(适合帧间目标连续的情况)==
    • 2.5 导出标注结果
  • 3. 标注文件格式转换代码——Datumaro 3D(json)转KITTI格式

1. CVAT安装教程

  1. 安装Docker
sudo apt-get update
sudo apt-get --no-install-recommends install -y apt-transport-https ca-certificates \curl \gnupg-agent \software-properties-commoncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) \stable"sudo apt-get update
sudo apt-get --no-install-recommends install -y \docker-ce docker-ce-cli containerd.io docker-compose-plugin

添加用户到docker组(以便无需sudo运行docker):

sudo groupadd docker
sudo usermod -aG docker $USER

重启系统以应用docker组的变更。

  1. 克隆CVAT源代码:
git clone https://github.com/opencv/cvat
cd cvat
  1. 安装chrome(若已安装可跳过):

cvat推荐只能用chrome浏览器
①安装包下载:

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

②使用 gdebi 工具自动安装 deb 包和依赖关系:

sudo apt install gdebi
sudo gdebi google-chrome-stable_current_amd64.deb
  1. 运行docker容器
    注意是在cvat目录下,第一次会下载需要的镜像
    以后每次开机都需要在这个路径下启动cvat的docker镜像
docker compose up -d

(若docker拉取镜像时出现失败超时,可参考解决方案)

  1. 创建一个超级用户
docker exec -it cvat_server bash -ic 'python3 ~/manage.py createsuperuser'

注意在邮箱处可以不填,否则可能报错。

  1. 启动CVAT
    在chrome浏览器中输入localhost:8080

2. 3D点云标注详细流程

2.1 创建3D点云标注任务(Task):

要创建任务,请在 Tasks(任务)页面上单击“+”,选择 Create new task (创建新任务)。
在这里插入图片描述
随后页面显示如下:
在这里插入图片描述

2.2 指定任务的参数:

  1. 在 Name 字段中,输入新任务的名称。
    在这里插入图片描述

  2. (可选)从 Projects 下拉列表中,为新任务选择一个项目。
    如果不想将任务分配给任何项目,请将此字段留空(建议)。
    在这里插入图片描述

注意:如果任务不属于项目,则以下步骤有效。
如果任务已分配给项目,则项目的标签将应用于该任务。

  1. 在 Constructor 选项卡上,单击 Add label (添加标签)。
    标签构造函数菜单将打开:
    在这里插入图片描述

  2. 在 Label name(标签名称)字段中,输入标签的名称。

  3. (可选)要将标签的使用限制为特定形状工具, 从 Label shape 下拉菜单中选择形状(默认Any即可)。

  4. (可选)选择标签的颜色,建议选择一些区分度比较大的颜色。
    在这里插入图片描述

  5. (可选)单击 Add an attribute 并设置其属性。(可以不设置)

  6. 单击 Continue 提交标签,就可以在后台保存下来,直接在label name上开始添加新标签,
    在这里插入图片描述
    在这里插入图片描述

单击 Cancel 终止当前标签并返回到标签列表,就会发现添加的标签已经列出来了。
在这里插入图片描述

2.3 数据集上传并进入任务job:

  1. 单击 Select files (选择文件)的虚线方框区域,或直接将文件拖拽到虚线框,以上传要注释的pcd/bin的压缩文件。(若格式bin,则cvat在标注时会直接转为pcd的格式)
    压缩文件的格式如下:
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

注意:文件名尽量做成类似这样以数字序号命名的格式,并且是按照时间排列的顺序,这样便于后续处理。

  1. 单击 Submit and open 以提交配置并打开已创建的任务,或 Submit and continue 以提交配置并启动新任务。文件上传成功会有提示:
    在这里插入图片描述

  2. 重新点击顶栏的Tasks即可看到新建的标注任务。
    在这里插入图片描述

  3. 点击Open进入Jobs页面,再点击job#xx 就可以开始标注了
    在这里插入图片描述

标注工作区界面如下:
在这里插入图片描述

2.4 标注说明:

  1. (注意:一定要经常保存,以免发生意外情况)

2.4.1. 可使用鼠标或键盘来改变视图:

在这里插入图片描述

您还可以使用键盘快捷键操作:

ActionKey
相机旋转Shift + 箭头(向上、向下、向左、向右)
左/右Alt+J/ Alt+L
上/下Alt+U/ Alt+O
放大/缩小Alt+K/ Alt+I

2.4.2. 使用长方体进行注释

有两个选项可用于3D标注:
• 形状:用于对象检测等任务。
• Track:使用插值来预测对象在后续帧中的位置。 将为每个对象分配一个唯一 ID,并在整个图像序列中维护。(更推荐,效率高)

1)使用shape方式进行批注(适合帧间目标不连续的情况)

要添加3D形状,请执行以下操作:

  1. 在对象窗格上,选择 Draw new cuboid>从下拉列表中选择标签>shape.
    在这里插入图片描述

  2. 光标后面将跟着一个cuboid。 双击对应的位置,将长方体放置在3D场景中。

  3. 使用投影调整长方体。 单击并按住鼠标左键可编辑投影上的标签形状。

  4. (可选)移动四个点中的一个以更改长方体的大小。

  5. (可选)要旋转长方体,请单击中间点 ,然后向上/向下或向左/向右拖动长方体。

  6. (可选)若相邻多帧均有相似大小的物体,可以选择传播(propagrate)当前帧的包围框到后续多帧以提高标注效率。
    在这里插入图片描述

(图中笔者是从第9帧开始的,传播了10帧,故到第19帧)

2)使用track方式进行批注(适合帧间目标连续的情况)

数据集中的文件若是按照采样时间顺序来排列,则可以根据物体在帧间移动的轨迹进行插值,从而大大节省人力。

  1. 在对象窗格上,选择 Draw new cuboid>从下拉列表中选择标签>track.
    在这里插入图片描述

  2. 为对象创建track(轨迹)(以所选container为例):
    通过单击创建,然后调整3D包围框
    在这里插入图片描述

  3. 但是此时会发现后面所有帧都被标注了3D框,且越往后偏离越大:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

对于这种问题,CVAT中具有自动插值的功能,通过选取一些关键帧(点击标注界面右侧的label状态栏的符号空心的五角星使其变成实心的五角星,即可将该帧变为关键帧),只需要将关键帧内的包围框手动对齐,然后就会发现关键帧之间的包围框便可以自动移动到了比较合适的位置,进而只需要微调就可以了。
在这里插入图片描述
在这里插入图片描述

  1. 结束当前目标的轨迹
    如图所示点击标注界面右侧的label状态栏的Switch Outside Property的按钮,即可终止后续帧track的操作,(注:操作了这一按钮的那一帧中对应的包围框也会消失失效)
    在这里插入图片描述
    在这里插入图片描述

  2. 如果对象只是在几个帧上不可见,然后再次出现,可以使用Merge功能合并多个单独的track合二为一,从而保证同一物体在不同帧中对应ID的一致性。
    在这里插入图片描述

① 这里以图像标注为例,为骑行者可见的时刻创建轨迹:

② 单击Merge按钮,然后再单击第一个track的任意矩形以及第二个track的任意矩形,依此类推:

③结束时再单击Merge按钮,使更改生效。这样就统一了数据集中同一物体在不同帧中的id了。
在这里插入图片描述

2.5 导出标注结果

  1. Save整个工程后,重新进入Task的界面,点击Export annotations:
    在这里插入图片描述

  2. 输出格式调整为Datumaro 3D 1.0,它自带的kitti输出的格式会有bug(没有帧信息),save images 的开关打开以保存原始点云数据
    在这里插入图片描述

  3. 如图点击顶栏跳到Requests中,然后点击刚刚导出的工程download即可
    在这里插入图片描述

  4. 最终下载的是一个zip的压缩包,内容如下:
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    这种格式可以通过python脚本来转成KITTI数据集的格式,代码我放在最后了。

  5. 最后记得将整个task也做一个备份留存以供后续的二次开发

在这里插入图片描述

3. 标注文件格式转换代码——Datumaro 3D(json)转KITTI格式

import json
import osdef json_to_kitti(json_path, output_dir):with open(json_path, 'r') as f:data = json.load(f)labels = data['categories']['label']['labels']os.makedirs(output_dir, exist_ok=True)# 遍历每一帧for item in data['items']:item_id = item['id']  # 使用 JSON 中的 'id' 值annotations = item['annotations']# 输出 KITTI 格式文件的路径,使用 'id' 命名output_path = f"{output_dir}/{item_id}.txt"with open(output_path, 'w') as f_out:# 遍历每个标注for annotation in annotations:label_id = annotation['label_id']label_name = labels[label_id]['name']# 提取 3D 立方体信息position = annotation['position']rotation = annotation['rotation']scale = annotation['scale']# KITTI 格式字段truncated = 0  # 默认为 0,因为未提供截断信息occluded = 1 if annotation['attributes']['occluded'] else 0alpha = rotation[2]  # 使用 Z 轴的旋转角作为方向角bbox_left = 0.0  # 2D 边界框位置,点云标注中通常为 0bbox_top = 0.0bbox_right = 0.0bbox_bottom = 0.0height = scale[2]  # 物体高度width = scale[0]   # 物体宽度length = scale[1]  # 物体长度x = position[0]    # 物体在相机坐标系中的 x 坐标y = position[1]    # 物体在相机坐标系中的 y 坐标z = position[2]    # 物体在相机坐标系中的 z 坐标rotation_y = rotation[2]  # KITTI 中物体绕 Y 轴的旋转角度# 将数据写入到 KITTI 格式文件f_out.write(f"{label_name} {truncated} {occluded} {alpha} "f"{bbox_left} {bbox_top} {bbox_right} {bbox_bottom} "f"{height} {width} {length} {x} {y} {z} {rotation_y}\n")json_to_kitti('/home/zpmc/code/demo_study_project/data_convert/default.json', '/home/zpmc/code/demo_study_project/data_convert/kitti_labels')

参考链接: https://blog.csdn.net/wxtcstt/article/details/134601044
https://docs.cvat.ai/docs/

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【读书笔记-《30天自制操作系统》-22】Day23

本篇内容比较简单,集中于显示问题。首先编写了应用程序使用的api_malloc,然后实现了在窗口中画点与画线的API与应用程序。有了窗口显示,还要实现关闭窗口的功能,于是在键盘输入API的基础上实现了按下按键关闭窗口。最后发现用上文…

诗文发布模板(python代码打造键盘录入诗文自动排版,MarkDown源码文本)

python最好用的f-string,少量代码打造键盘录入诗文自动排版。 (笔记模板由python脚本于2024年09月19日 19:11:50创建,本篇笔记适合喜欢写诗的pythoner的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free&am…

Apache subversion 编译流程

目录 1. 概述2. 依赖库简介2.1 Expat2.2 Apache apr2.3 Apache apr-iconv2.4 Apache apr-util2.5 Zlib2.6 OpenSSL2.7 Sqlite2.8 Apache Serf2.9 Apache subversion3. 编译3.1 Expat编译3.1.1 源码信息3.1.2 CMake-GUI3.1.3 编译步骤3.2 APR编译3.2.1 源码信息3.2.2 编译步骤3.…

【笔记】2.1 半导体三极管(BJT,Bipolar Junction Transistor)

一、结构和符号 1. 三极管结构 常用的三极管的结构有硅平面管和锗合金管两种类型。各有PNP型和NPN型两种结构。 左图是NPN型硅平面三极管,右图是PNP型锗合金三极管。 从图中可见平面型三极管是先在一块大的金属板上注入杂质使之变成N型,然后再在中间注入杂质使之变成P型,…

倒序循环(一)

题目描述 输入一个正整数n,输出从 n~ 1 递减的序列。 输入格式 一行一个整数 n 输出格式 n 行,每行一个符合题目要求的整数 样例数据 样例输入#1 5样例输出#1 5 4 3 2 1样例输入#2 6样例输出#2 6 5 4 3 2 1数据范围 对于100%的数据&#xff…

Java企业面试题2

1.语言的分代: 第1代:机器语言 机器语言是最底层的计算机编程语言,它是由二进制数构成的一系列指令,直接与计算机硬件交互。每个二进制位模式代表一条特定的指令或数据地址。因为它是直接在硬件上执行的,所以运行效率…

Java 23 的12 个新特性!!

Java 23 来啦!和 Java 22 一样,这也是一个非 LTS(长期支持)版本,Oracle 仅提供六个月的支持。下一个长期支持版是 Java 25,预计明年 9 月份发布。 Java 23 一共有 12 个新特性! 有同学表示&…

xmake与包管理:又一个现代c++构建工具?

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 主要起因是我在逛Reddit帖子时,看到关于一些c构建系统的评价. cmake似乎有些过于复杂,它与vcpkg,conan的包管理之间的"融合"可能在有些时候也显得麻烦. 一些人尝试了我没见过的选项, 所以这里主要试试除了…

Java重修笔记 第五十七天 坦克大战(七)多线程基础 - 编程练习

1. 线程之间的协调控制(通知方式) public class Homework04 {public static void main(String[] args) {// 在 main 方法中启动两个线程// 第一个线程内循环打印 1 到 100 以内的整数// 直到第二个线程从键盘读取到 "Q" 指令后结束第一个线程…

深入剖析大模型原理——Qwen Blog

1. 输入部分 Text:原始输入文本,模型需要处理的自然语言数据。Tokenizer:分词器,将输入文本转换为词汇表中的索引(ID),便于后续处理。Input_ids:经过分词处理后的ID序列&#xff0c…

交流回馈老化测试负载的智能升级

在电子设备的生产过程中,老化测试是不可或缺的环节。老化测试主要是通过模拟设备长时间工作的情况,检测设备在经过一定时间的使用后,其性能是否会发生降低,是否存在安全隐患等。老化测试负载是老化测试中的重要组成部分&#xff0…

今日所学啊

ArcGIS打不开焦点统计如何解决_arcgis焦点统计打不开-CSDN博客 好吧其实最后焦点统计还是不行&#xff0c;我就去ArcGIS Pro里做焦点统计了哈哈哈哈哈哈哈 visual studio多工程项目管理_visual studio 的模块管理-CSDN博客 1.今天成功#include <QNetworkReply>不画红线…

【MYSQL表的增删改查(基础)】

MYSQL表的增删改查&#xff08;基础&#xff09; 一、CRUD二、新增&#xff08;Create&#xff09;2.1 单行数据全列插入2.2 多行数据指定列插入 三、查询&#xff08;Retrieve&#xff09;3.1 全列查询3.2 指定列查询3.3 查询字段为表达式3.3.1 表达式不包含字段3.3.2 表达式包…

react是什么?

文章目录 核心特点1. **组件化**2. **虚拟 DOM** 3. **声明式编程**4. **单向数据流**5. **JSX 语法**6. **Hooks** react的优势劣势 React 是一个由 Facebook 开发和维护的开源 JavaScript 库&#xff0c;用于构建用户界面&#xff0c;特别是单页应用程序&#xff08;SPA&…

[PICO VR眼镜]眼动追踪串流Unity开发与使用方法,眼动追踪打包报错问题解决(Eye Tracking/手势跟踪)

前言 最近在做一个工作需要用到PICO4 Enterprise VR头盔里的眼动追踪功能&#xff0c;但是遇到了如下问题&#xff1a; 在Unity里面没法串流调试眼动追踪功能&#xff0c;根本获取不到Device&#xff0c;只能将整个场景build成APK&#xff0c;安装到头盔里&#xff0c;才能在…

枚举(not二分)

前言&#xff1a;这一题似乎用不了二分以及三分&#xff0c;害我写这么久&#xff0c;但是查找下一个元素的时候要用到二分查找 题目地址 #include<bits/stdc.h> using namespace std; #define endl "\n"int n; const int N (int)2e510; vector<int> a;…

OceanBase 中 schema 的定义与应用

背景 经常在OceanBase 的问答社区 里看到一些关于 “schema 是什么” 的提问。 先纠正一些同学的误解&#xff0c; OceanBase 中的 Schema 并不简单的等同于 Database&#xff0c;本次分享将探讨 OceanBase 中的Schema是什么&#xff0c;及一些大家经常遇到的问题。 具体而…

JavaDS —— 图

图的概念 图是由顶点集合以及顶点之间的关系组成的一种数据结构&#xff1a;G &#xff08;V&#xff0c;E&#xff09; 其中 V 表示的是顶点集合 &#xff1a; V { x | x 属于某个数据对象集} 是有穷非空集合 E 叫做边的集合 &#xff1a; E {(x, y) | x, y 属于 V} 或者 …

UE5源码Windows编译、运行

官方文档 Welcome To Unreal Engine 5 Early Access Learn what to expect from the UE5 Early Access program. 链接如下&#xff1a;https://docs.unrealengine.com/5.0/en-US/Welcome/#gettingue5earlyaccessfromgithub Step 0&#xff1a;找到UE5源码 直接先上链接 https…

MySQL原理之UUID主键分析,插入或更新语法分析

文章目录 1 MySQL不能用UUID做主键1.1 前言1.2 mysql和程序实例1.2.1 准备工作1.2.2 开始测试1.2.3 程序写入结果1.2.4 效率测试结果 1.3 使用uuid和自增id的索引结构对比1.3.1 自增id1.3.2 uuid 1.4 自增id缺点1.5 雪花算法 2 插入或更新2.1 on duplicate key2.1.1 定义2.1.2 …