指南 3个标注团队操作手册:提升标注速度与质量

带音频视频同步的时间序列标注

该模板展示了通过将音频或视频帧映射到相应的时间序列时间戳,实现媒体流与对应传感器数据的同步。

例如:

备注

要求: Label Studio 版本 ≥ 1.20

时间单位与同步

所有同步消息使用从每个组件启动开始的相对秒数。

有两种类型的配置,您使用的配置决定了时间序列如何转换相对秒数:

  • 基于时间: 转换为绝对时间戳
  • 基于索引: 使用相对秒数作为索引

基于时间的时间序列

  • 将相对秒数转换为绝对时间戳。
  • 保持与媒体的精确时间对齐,支持任意自定义采样率
  • Examples:
    • 视频中的30秒 = 时间序列中从开始算起的30秒
    • 如果时间序列从第5秒开始,它将作为其他媒体的起始点。因此,视频的0秒将从时间序列的第5秒开始,这个偏移量将始终被应用。

要指定基于时间的时间序列,请使用以下格式:

<TimeSeries name="ts" timeColumn="timestamp" timeFormat="%Y-%m-%d %H:%M:%S">

基于索引的时间序列

  • 使用直接索引作为相对秒数
  • 媒体中的每一秒对应时间序列中的一个索引,采样率始终为1赫兹
  • 主要适用于调试和测试
  • Example:
    • 视频中的30秒 = 时间序列中的索引30

要指定基于索引的时间序列,请使用以下格式:

<TimeSeries name="ts">

最佳实践

在以下情况下使用时序时间序列:

  • 数据包含实际时间戳
  • 需要精确的时间对齐
  • 处理多种媒体类型

在以下情况下使用基于索引的时间序列:

  • 数据是连续的
  • 无实际时间戳可用
  • 简单的1样本<=>1秒与媒体时间的映射就足够了

处理长度不匹配问题

您的数据可能存在长度不匹配的情况。当出现这种情况时:

  • 同步工作至较短组件的长度
  • 组件在各自端点停止
  • 不会发生数据丢失,但同步会在较短组件结束时停止

标注配置

基于索引的时间序列 + 视频 + 时间序列标签

基于索引的时间序列(X轴无时间戳)。

备注

由于TimeSeries标签中未指定时间轴,因此一个值对应一秒。视频同步采用这一原则——若未提供时间戳,则一个采样点等于一秒。

<View>
  <Video name="video" value="$video" sync="group_a"/>
  
  <TimeSeries name="timeseries"
              value="$ts" valueType="json"
              sync="group_a" sep=","
              overviewWidth="10%"
              >
    <Channel column="value" strokeColor="#FF0000"/>
    <Channel column="value" strokeColor="#00FF00"/>
  </TimeSeries>
  
  <TimeSeriesLabels name="labels" toName="timeseries">
    <Label value="action"/>
    <Label value="pause"/>
  </TimeSeriesLabels>

</View>

<!-- {
  "video": "https://app.heartex.ai/static/samples/opossum_snow.mp4",
  "ts": {
      "value": [
        10.7036820361892644,
        -0.18120536109567212,
        -0.39251488391214157,
        1.3384817293995075,
        0.8779675446349394,
        -0.1511946071051955,
        -0.7955547028255082,
        1.0736798948078534,
        1.1266164855584428,
        -0.440291574562604,
        -0.8436786901744359,
        -0.24956239687939094,
        1.268049926141147,
        0.6300808834120004,
        1.7946935071842107,
        -0.37700464705843,
        0.706518542026297,
        -0.45787451607104046,
        -2.3643354623876607,
        0.13984274721398307,
        0.3174445171792305,
        -1.8162371732091722,
        -0.30289394872251374,
        -0.730112449190387,
        -1.6852497246079239,
        -1.0473893262227658,
        0.10416951356137397,
        -2.0266185534759633,
        -0.05196549263706541,
        0.4436085233243668,
        -0.0956064205420074,
        -1.1790065141112944,
        -0.015063840978932763,
        0.28691755509866407,
        1.4122332721986657,
        0.40127732957527523,
        1.546243544663401,
        0.11119508061291504,
        -0.499517691828469,
        -0.02922576888373752,
        -0.8454178734108769,
        0.19122400060485445,
        0.6914340334390281,
        -0.18047241277757645,
        -0.6394589243120249,
        1.0019886671810008
      ]
  }
} -->

基于时间轴的多重时间序列 + 音频 + 视频 + 时间序列标签

  • 基于时间的时间序列
  • 时间序列、音频和视频同步在一起
  • 选项和时间轴标签用作标注的控制标签
<View>
  <Video name="video" value="$video" sync="group_a"/>
  <!-- <Audio name="audio" value="$video" sync="group_a"/> -->
  
  <TimeSeriesLabels name="timelinelabels" toName="accel_timeseries">
    <Label value="A"/>
    <Label value="B"/>
  </TimeSeriesLabels>  

  <TimeSeries 
              name="accel_timeseries"
              value="$accel_data"
              sync="group_a"
              timeColumn="time"
              timeFormat="%H:%M:%S.%f"
              timeDisplayFormat="%H:%M:%S.%f"
              overviewWidth="10%"
  >
    <Channel column="accel_x" strokeColor="#FF0000" height="100"/>
    <Channel column="accel_y" strokeColor="#00FF00" height="100"/>
  </TimeSeries>
  
  <TimeSeries 
              name="gyro_timeseries" 
              value="$gyro_data" 
              sync="group_a"
              timeColumn="time"
              timeFormat="%H:%M:%S.%f"
              timeDisplayFormat="%H:%M:%S.%f"
              overviewWidth="10%"
  >
    <Channel column="gyro_x" strokeColor="#0000FF" height="100"/>
    <Channel column="gyro_y" strokeColor="#FF00FF" height="100"/>
  </TimeSeries> 

</View>

<!-- {
  "video": "https://app.heartex.ai/static/samples/opossum_snow.mp4",
  "accel_data": "https://app.heartex.ai/samples/time-series.csv?time=time&values=accel_x%2Caccel_y&sep=%2C&tf=%H:%m:%d.%f",
  "gyro_data": "https://app.heartex.ai/samples/time-series.csv?time=time&values=gyro_x%2Cgyro_y&sep=%2C&tf=%H:%m:%d.%f"
}
-->

时间序列数据文件 time-series-accel.csv 中 accel_x 和 accel_y 的示例

time,accel_x,accel_y
00:01:01.000000,-0.056646571671882806,2.1066649495524605
00:01:02.000000,-0.6888765232989033,0.35646668995794306
00:01:03.000000,-0.23512086306647553,0.5799351613084716
00:01:04.000000,-0.9314772647682944,-0.5195693066279311
00:01:05.000000,1.321119143958512,-0.622026749003922
00:01:06.000000,0.10592100887528152,0.15477501359739493
00:01:07.000000,-0.6261150686384155,0.5624264458111049
00:01:08.000000,1.0829322997587332,-1.9590268928992862
00:01:09.000000,-1.2267135177322928,-0.4538764395229617
00:01:10.000000,1.6705781810127622,0.38407182850093363

时间序列数据文件 time-series-gyro.csv 中 gyro_x 和 gyro_y 的示例

time,gyro_x,gyro_y
00:01:01.000000,-0.776563940219835,-1.1115451852904443
00:01:02.000000,0.17111212343134966,-1.377696478819913
00:01:03.000000,-1.168085910547026,-0.8500307427257534
00:01:04.000000,-0.13947878605597916,0.9062482653127198
00:01:05.000000,0.3079887618179474,-1.6722497873634719
00:01:06.000000,-0.3825838786476411,-1.242585234780504
00:01:07.000000,-0.7015245817392025,-1.712515499827561
00:01:08.000000,-0.3437952109000775,-0.9337512501019165
00:01:09.000000,-0.19464021971045084,-0.9653381620475747
00:01:10.000000,-0.29753925483100785,-0.7699832734123578