本项目是在原始 X-AnyLabeling 项目基础上进行 Fork 后新增开发的功能。时序事件标注是一个全新的功能模块,用于支持视频帧序列中的事件标注和管理,为原项目增添了强大的视频时序标注能力。
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 7 天前 | ||
| 2 个月前 | ||
| 7 天前 | ||
| 2 个月前 | ||
| 7 天前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 7 天前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 |
X-AnyLabeling-Temporal
本仓库是基于 X-AnyLabeling Fork 扩展的版本,新增了两项核心功能:时序事件标注和数据云端同步。
目录
时序事件标注
功能概述
时序事件标注用于对手术视频进行语义标注,支持在视频时间轴上标记事件片段。通过主界面左下方的按钮打开独立对话框,提供视频播放、时间轴可视化、标注管理等功能。
标注类别
支持三种标注类别,每种使用不同颜色区分:
| 类别 | 颜色 | 说明 |
|---|---|---|
| 手术阶段 | 绿色 | 手术过程中的阶段划分 |
| 手术动作 | 蓝色 | 具体的手术操作动作 |
| 关键事件 | 橙色 | 需要特别标记的关键时刻 |
主要功能
- 视频播放控制:播放/暂停、逐帧前进/后退、倍速播放
- 时间轴可视化:在时间轴上显示已标注的事件片段,支持拖拽选择起止帧
- 标注管理:添加、编辑、删除标注,支持复选框控制显示
- 筛选搜索:按类别筛选,按名称/描述搜索
- JSON 导入/导出:自动保存标注到 JSON 文件,支持手动导出
- 视频片段导出:将选中的标注片段导出为独立视频文件(支持 FFmpeg 和 OpenCV 两种方式)
快捷键
| 快捷键 | 功能 |
|---|---|
← / → |
逐帧前进/后退 |
Ctrl + ← / Ctrl + → |
倍速跳帧 |
空格 |
播放/暂停 |
S |
设置当前帧为起点 |
E |
设置当前帧为终点 |
Ctrl + S |
保存标注 |
Esc |
取消编辑 |
使用方法
- 打开对话框:点击主界面左下方的"视频时序标注"按钮。
- 加载视频:点击"加载视频"按钮,选择手术视频文件。
- 设置起止帧:
- 播放视频到目标位置,按
S设置起点,按E设置终点 - 或在时间轴上拖拽选择时间段
- 或点击"起点"/"终点"按钮
- 播放视频到目标位置,按
- 填写标注信息:选择类别、输入名称和描述。
- 保存标注:点击"保存"按钮或按
Ctrl + S。 - 导出:
- 点击"导出 JSON"手动导出标注文件
- 点击"导出片段"将选中标注导出为视频片段
输出格式
标注数据自动保存在视频同目录下,文件名为 {视频名}_annotations.json,格式如下:
[
{
"id": 1,
"type": "手术阶段",
"name": "切开皮肤",
"description": "使用电刀切开皮肤",
"start_frame": 0,
"end_frame": 450,
"start_time": 0.0,
"end_time": 15.0
},
{
"id": 2,
"type": "手术动作",
"name": "抓取血管",
"description": "使用持针钳抓取血管准备吻合",
"start_frame": 300,
"end_frame": 1200,
"start_time": 10.0,
"end_time": 40.0
}
]
字段说明:
id:标注的唯一标识(自增整数)type:标注类别(手术阶段 / 手术动作 / 关键事件)name:标注名称description:标注描述start_frame/end_frame:起止帧编号(从 0 开始)start_time/end_time:起止时间(秒,根据帧率和 FPS 计算)
数据云端同步
功能概述
云端同步功能实现了本地工作空间与远程存储服务之间的数据同步,支持图片文件和标注文件的双向传输。主要特性:
- 基于 REST API 的通信:与后端服务通过
/v1/cloud/*接口交互,使用 Token 认证 - 工作空间管理:支持多工作空间的创建、切换、删除,通过 v2 API 管理用户和工作空间
- 文件状态追踪:基于 MD5 校验和对比本地与远程文件,标记为 已同步 / 仅本地 / 仅远程 / 已修改 / 冲突
- 批量并发传输:使用
ThreadPoolExecutor多线程并发上传/下载(默认 4 线程) - 自动同步:标注文件保存时自动触发上传,同时检查对应图片文件是否需要同步
- 冲突检测:检测到本地和远程文件不一致时弹出冲突解决对话框
- 异步非阻塞:所有网络操作在
QThread工作线程中执行,UI 保持响应 - 指数退避重试:对网络错误和服务端错误(5xx、429)自动重试,最多 3 次
架构设计
CloudSyncWidget (UI 面板)
│
▼
CloudSyncManager (业务逻辑 / 状态机)
│
├── CloudSyncAPI (HTTP 客户端,REST API 封装)
│ └── requests.Session (线程安全,Token 认证)
│
└── SyncWorker (QThread 后台线程)
└── ThreadPoolExecutor (并发文件传输)
| 模块 | 文件 | 职责 |
|---|---|---|
| UI 面板 | views/labeling/widgets/cloud_sync_widget.py |
连接配置、工作空间选择、文件列表展示、操作按钮 |
| 业务逻辑 | services/cloud_sync/sync_manager.py |
连接管理、文件对比、同步编排、状态信号 |
| API 客户端 | services/cloud_sync/sync_api.py |
HTTP 请求封装、认证、重试逻辑、错误处理 |
| 工作线程 | services/cloud_sync/sync_worker.py |
异步任务执行、文件扫描、校验和计算 |
使用方法
- 打开面板:在侧边栏勾选"云端同步"复选框,展开同步面板。
- 连接服务:输入服务器地址(如
https://api.example.com)和 API Key,点击"连接"。 - 选择工作空间:连接成功后,从工作空间下拉框选择目标工作空间,或点击"新建"创建新工作空间。
- 同步操作:
- 上传全部:将所有"仅本地"和"已修改"的文件上传到远程
- 下载全部:将所有"仅远程"和"已修改"的文件下载到本地
- 同步:先上传再下载,执行双向同步
- 自动同步:勾选"保存时自动同步"后,每次保存标注文件会自动上传到远程。
API 接口
云端同步与后端通过以下 REST API 交互:
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /v1/cloud/connect |
认证连接 |
| POST | /v1/cloud/disconnect |
断开连接 |
| GET | /v1/cloud/workspaces |
获取工作空间列表 |
| POST | /v1/cloud/workspaces |
创建工作空间 |
| PUT | /v1/cloud/workspaces/{workspace} |
更新工作空间配置 |
| DELETE | /v1/cloud/workspaces/{workspace} |
删除工作空间 |
| POST | /v1/cloud/workspaces/resolve |
通过本地路径解析工作空间 |
| GET | /v1/cloud/workspaces/{workspace}/files |
获取远程文件列表 |
| POST | /v1/cloud/workspaces/{workspace}/upload |
上传文件(multipart/form-data) |
| GET | /v1/cloud/workspaces/{workspace}/download/{filename} |
下载文件 |
| DELETE | /v1/cloud/workspaces/{workspace}/files/{filename} |
删除远程文件 |
| GET | /v1/cloud/workspaces/{workspace}/checksum/{filename} |
获取远程文件校验和 |
| GET | /v1/users/me |
获取当前用户信息 |
认证方式:HTTP Header Token: <api_key>
注意事项
- 时序标注基于视频帧索引,从 0 开始计数
- 时序标注数据自动保存在视频同目录下,文件名为
{视频名}_annotations.json - 视频片段导出优先使用 FFmpeg(速度快),如未安装则回退到 OpenCV(需要重新编码)
- 云端同步支持的文件类型:图片(
.jpg,.jpeg,.png,.bmp,.tiff,.tif,.webp)和标注文件(.json) - 自动同步仅在已连接且已选择工作空间时生效
- 冲突解决目前提供三种选项:保留本地、覆盖本地、保留两者
反馈与建议
- 原项目地址:X-AnyLabeling
- 反馈方式:请通过本仓库的 GitHub Issues 提交问题和建议
基于 X-AnyLabeling Fork 版本开发
Made with ❤️ by XShura