2026.06.03征图日记28(终于摸到核心了?)

今天上午一直在熟悉webai-lite的代码。一边在改mentor留下的bug,一边在问Ai整个项目的逻辑结构

经过昨天的忙碌之后,我决定每天上午写代码,改bug,下午就开始标注,最多也就200张或者到下午5点,两者满足其一就不标了,剩下的时间可以看看八股或者刷刷算法。这样也不至于忙得工作日志都忘了写~~

骏哥让我把那个推理客户端从git上拉下来,然后说是我的win电脑上没有显卡,要帮我找一台工控机来运行推理客户端。我去兄弟!终于还是让我摸到这一层了吗?接下来我就可以了解到底是如何部署服务的,具体如何推理的,如何训练的,一些细节等等~

我发现写代码的时候时间过得真快,一下子一上午就过去了,感觉也没干什么。干标注的时候就觉得时间很漫长~

下午骏哥让我自己先cmake一下,不懂的问他,我直接一个cmake之后报错,没有Qt环境?安装好对应vs 2019 的Qt环境之后,cmake .. 又报错?没有安装cuda环境?我看了一下工控机上的cuda版本是12.9,我直接跑到英伟达官网安装一手。把CUDAToolkit套件放在指定目录(直接放在E盘根下了,不要学我~)。之后总算cmake过了,之后就是执行 cmake --build . --config Release 把各种环境变量(QT的环境变量、cuda的环境变量)都配置好,之后生成了一个Release目录,下面有一个WebAIClient.exe的文件,点击之后还缺少动态库?执行 windeployqt.exe WebAIClient.exe 添加Qt的动态库之后再次点击有报错?缺少FSAI_Core_ProccessV22.dll?这个东西是在webai2.0-dev下的3rdParty目录下的,现在考虑如何把这个目录下的所有东西都搬过去。或者尝试直接在工控机上运行看能不能行~。OK不行,之前都是问豆包,这次问一下cc看有什么办法吧~

字集(hot100 回溯)

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
class Solution {
public:
vector<vector<int>> ans;
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> output;
dfs(nums, output, 0);
return ans;
}
// pos当前位置选 or 不选
// nums 原数组
// output 当前搜索到的数组
void dfs(vector<int>& nums, vector<int>& output, int pos) {
if (pos == nums.size()) {
// 无论output里面有几个元素 都把nums搜索完了
ans.emplace_back(output);
return;
}

// 选pos
output.push_back(nums[pos]);
dfs(nums, output, pos + 1);
// 恢复现场
output.pop_back();

// 不选pos
dfs(nums, output, pos + 1);
}
};

静姐说晚上杨总在公司会所请大家吃小龙虾,这岂有不去的道理?
我chovy,又说没位置了让我下次,你给我通知好的啊!(没事正好减脂,去吃了小龙虾就没时间做有氧了)


今日工作内容

  1. 优化webai-lite标注界面体验
  2. 配置推理客户端环境
  3. 蓝膜标注83张

下阶段计划

  1. 梳理推理客户端代码结构
  2. 将推理客户端在工控机上跑起来
  3. 继续标注

btw:

完成两个关联特性:

  1. 多 mask 独立对象架构——从单全局 canvas 改为 MaskObjectManager 管理多个独立 canvas 层,mask 与矢量对象在 model.objects[] 中同级,支持选中高亮(调暗+轮廓)、独立编辑删除、undo 像素恢复。
  2. 统一缺陷编辑模型——多边形和矩形工具不再创建矢量对象,改为光栅化填充到 mask canvas 层,所有缺陷统一为 mask。旧数据加载时自动光栅化。同步沉淀 editor-architecture.md 和 editor-canvas-guide.md spec。

修复标注界面多个问题:

  1. 统一缺陷编辑模型——polygon/rectangle 光栅化为 mask,三种工具=三种画笔;
  2. 选中才能编辑——createNew 替代 classId 分组,擦除未选中无操作;
  3. 跨图片 mask 残留——切图时 clearAll;
  4. 保存丢失同 classId mask——prepareMaskData 按 id 匹配;
  5. 选中交互优化——点击空白取消、mask 模式下 click 切换选中、classId 双向同步防循环;
  6. 画笔尺寸跨图持久化——状态提升到页面级;
  7. bbox 选中框替代轮廓追踪。同步更新 editor-architecture.md 和 editor-canvas-guide.md spec。

修复切图时幽灵缺陷的根因:

  • useCanvas 第一个 useEffect 在异步图片加载期间闭包捕获了旧的 initialObjects,加载完成后用旧数据 clearAll 清掉了第二个 useEffect 已恢复的正确 mask。
  • 修复方案:第一个 useEffect 只负责 canvas 创建和图片加载,所有对象同步完全交给第二个 useEffect(依赖 initialObjects + ready)。

WebAI Lite 项目架构分析总结

日期: 2026-06-03
会话主题: 全面了解 WebAI Lite 项目架构

会话路线图

1. 入口点:converter 包

  • 问题: converter 目录下的包是干什么的
  • 答案: LSF JSON → 训练掩码(PNG class index)转换器
  • 关键点: 只支持旧的 LSF 格式,不支持当前 CVAT 格式

2. 探索临时目录

  • 问题: api 目录下的 _tmp* 是干什么的
  • 答案: 测试临时目录(COCO 导出测试、Device Manager 输出测试)

3. 工作区结构

  • 问题: _workspace 里面的目录是干什么的
  • 答案: 用户工作区根目录
    • current/images/ - 用户上传图片
    • current/annotations/ - vector 标注 JSON
    • current/masks/ - mask PNG(训练用)
    • current/jobs/ - 任务队列
    • current/models_parameter/ - 模型参数覆盖
    • current/flows_parameter/ - 推理流程覆盖

4. 后端包结构

  • 问题: webai_lite_api 里面的东西
  • 答案: FastAPI 单进程服务
    • 入口层: main.py, config.py, errors.py
    • 路由层: routes/(health, workspace, annotations, artifacts, catalog, jobs, train, infer)
    • 服务层: services/(paths, workspace, job_center, catalog, cvat_coco_export, cvat_mask_decode)
    • 设备管理: device_manager/(可选,与 webai2.0 协议对齐)

5. 推理数据流

  • 问题: 推理客户端是如何读到图片的
  • 答案: 两种模式
    • 本机模式: 直接读取文件系统 {workspace_root}/current/images/{stem}.{ext}
    • device_manager 模式: 打包成 COCO zip 通过 TCP 发送

6. 网络访问方式

  • 问题: 直接文件系统访问是通过网络读取吗
  • 答案: 不是,客户端和服务端在同一台机器,直接读取本地磁盘

7. converter 包的局限性

  • 问题: converter 支持画笔和多边形数据吗
  • 答案: 不支持,只支持 LSF 格式(百分比坐标)
    • 当前 CVAT 格式由 cvat_mask_decode.py 和 cvat_coco_export.py 处理

8. 标注数据处理

  • 问题: cvat_coco_export.py 和 cvat_mask_decode.py 的作用
  • 答案:
    • cvat_mask_decode.py: 解码器,RLE → numpy 数组
    • cvat_coco_export.py: 导出器,生成 COCO 格式 zip
    • converter: 转换器,生成 masks/*.png(旧方案)

9. COCO 格式

  • 问题: COCO 是什么
  • 答案: Common Objects in Context,计算机视觉领域标准数据集格式
    • 统一格式:检测、分割、关键点都支持
    • 工具链丰富:pycocotools、Datumaro
    • 评估标准:mAP、IoU 等指标计算

10. 打包流程

  • 问题: 标注完成后会打包成 COCO zip 吗
  • 答案: 是的,提交训练/推理任务时自动打包
    • code.zip: 训练代码包
    • config.zip: 配置参数
    • sample.zip: COCO 数据集(图片+标注)
    • res_dir: 输出目录

11. 任务配置

  • 问题: device_manager_enabled 在哪里修改
  • 答案: 在 .env 文件或系统环境变量中修改
    • WEBAI_LITE_DEVICE_MANAGER_ENABLED=true
    • WEBAI_LITE_DEVICE_SUBMIT_BRIDGE_ENABLED=true

12. 训练流程

  • 问题: 提交训练后的流程
  • 答案:
    1. 创建 jobs/*.json(status=submitted)
    2. 触发 schedule_disk_job_bridge()
    3. 打包 COCO zip
    4. 发送给设备或本机执行

13. 通信协议

  • 问题: HTTP 和 TCP 如何管理
  • 答案: 两种协议并行
    • HTTP (8001): 状态查询、控制命令
    • TCP (8002): 心跳、大文件传输

14. 自定义 TCP 协议

  • 问题: 如何自定义 TCP 协议格式
  • 答案:
    • 固定长度字段: Command(16B), TaskID(36B), ModelType(32B)
    • 变长字段: 先读长度前缀,再读内容
    • 大文件: 分块传输(1MB/块)

15. 粘包和队头阻塞

  • 问题: 如何解决粘包和队头阻塞
  • 答案:
    • 粘包: 固定长度 + 长度前缀
    • 队头阻塞: 每设备独立连接 + 事件锁

16. 数据块大小

  • 问题: 为什么数据块是 1MB
  • 答案: 平衡点
    • 系统调用: 适中
    • 内存占用: 适中
    • 事件循环: drain() 频率合理
    • 磁盘 I/O: 对齐 4KB 块

核心架构图

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
┌─────────────────────────────────────────────────────────────┐
│ 前端 (React) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 数据页 │ │ 标注页 │ │ 训练页 │ │ 推理页 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ 后端 (FastAPI) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 路由层 │ │
│ │ /api/workspace /api/annotations /api/jobs ... │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 服务层 │ │
│ │ workspace.py job_center.py cvat_coco_export.py │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 设备管理 (可选) │ │
│ │ TCP 8002 (心跳+文件传输) HTTP 8001 (状态查询) │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ 数据存储 │
│ _workspace/current/ │
│ ├── images/ (原图) │
│ ├── annotations/ (CVAT JSON) │
│ ├── masks/ (PNG, 训练用) │
│ ├── jobs/ (任务队列) │
│ ├── models_parameter/ (模型覆盖) │
│ └── flows_parameter/ (流程覆盖) │
└─────────────────────────────────────────────────────────────┘

数据流总结

标注流程

1
2
3
用户画笔/多边形 → 前端生成 CVAT 格式 → PUT /api/annotations/{id}
→ PUT /api/annotations/{id}/mask
→ 保存到 annotations/*.json

训练流程

1
2
3
4
5
6
7
提交训练 → jobs/*.json (submitted)
→ schedule_disk_job_bridge()
→ prepare_train_bundle()
→ export_workspace_to_coco_zip() → sample.zip (COCO 格式)
→ POST /api/tasks → 设备管理器
→ TCP 发送 COCO zip → 设备执行训练
→ 训练完成 → artifacts/latest/

推理流程

1
2
3
4
5
6
提交推理 → jobs/*.json (submitted)
→ prepare_infer_bundle()
→ export_workspace_to_coco_zip() → infer_sample.zip
→ POST /api/tasks → 设备管理器
→ TCP 发送 COCO zip → 设备执行推理
→ 推理完成 → 结果回传

关键设计决策

1. 为什么用 CVAT 格式而不是 COCO 格式?

  • CVAT 格式适合编辑(支持撤销/重做)
  • COCO 格式适合训练(标准化)
  • 导出时动态转换

2. 为什么用自定义 TCP 而不是 HTTP?

  • 大文件传输效率更高
  • 心跳机制更轻量
  • 双向通信更灵活

3. 为什么每设备独立连接?

  • 避免队头阻塞
  • 任务串行化(同一设备)
  • 任务并行化(不同设备)

4. 为什么用 1MB 数据块?

  • 系统调用次数适中
  • 内存占用适中
  • asyncio 事件循环友好
  • 磁盘 I/O 对齐

待解决问题

  1. 上传新图片时原图消失: _clear_workspace_content() 会清空所有数据
  2. macOS ._ 文件*: shutil.copy2 会生成 AppleDouble 文件
  3. converter 包过时: 只支持 LSF 格式,不支持当前 CVAT 格式