|
| 1 | +# 非线性结构图像捕获与持久化(结构图)+ v0.7.7 修复项——头脑风暴与设计规格 |
| 2 | + |
| 3 | +**状态**: 已裁决(2026-08-20 用户头脑风暴:方案 A+ 批量+屏内选优;混合触发;会话内图库;两个修复项并入) |
| 4 | +**版本**: v0.7.7(0.7 下一个小版本,独立发布,不与 v0.8.0 AI 合并) |
| 5 | +**关联**: 版面分析(REQ-047,layout_analyzer.rs 规则版)· 屏卡体系(REQ-155~161,[ADR-015](../../adr/ADR-015-screen-cards-ocr.md))· 三层图存储(REQ-051/110,image_store)· [ADR-010](../../adr/ADR-010-gap-filling-ai.md)(图语义"必须理解才能还原"→ 本版用"图像即产物"兜底)· REQ-056/058(AI 语义重建 V1.0) |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## 一、问题与动机 |
| 10 | + |
| 11 | +版面分析(v0.5.0)已能把帧区域分类为 text/table/formula/code/image/unknown,但**非线性文本结构**(含义依赖二维排布、线性 OCR 必然失真的内容)缺少"图像级持久化"闭环: |
| 12 | + |
| 13 | +| 结构类型 | 现状 | 缺口 | |
| 14 | +|---------|------|------| |
| 15 | +| 表格/公式/代码 | 实时链路已存裁剪图,但仅作精修中间产物(`crop/` 命名空间,REQ-159) | 无持久化记录、无图库消费、无区域级配图基础 | |
| 16 | +| 流程图/思维导图/架构图/图表(Image/Unknown) | 完全无裁剪无持久化;OCR 线性文本必然失真;AI 语义重建(REQ-056/058)V1.0 才实装 | **中间缺"图像即产物"兜底**——纯本地铁律下唯一诚实路径是先保存图 | |
| 17 | +| 笔记配图 | 只有整帧 full 图(屏段落配图,REQ-160) | 无区域级图(本版不做笔记消费,表留 screen_id 锚点待下版) | |
| 18 | + |
| 19 | +**核心洞察**: 语义重建(V1.0 AI 补缝)之前,"保存图像本身"是本地优先架构下对非线性结构的正确降级——图比线性文本诚实。 |
| 20 | + |
| 21 | +## 二、头脑风暴裁决(2026-08-20) |
| 22 | + |
| 23 | +| 议题 | 裁决 | |
| 24 | +|------|------| |
| 25 | +| 范围 | **两者都要**:结构三类(表格/公式/代码)+ 视觉型图结构(Image 区域)统一获得图像持久化能力 | |
| 26 | +| 触发方式 | **混合**:自动覆盖高频(结构三类 + Image 区域过过滤);手动框选补充低频/漏检 | |
| 27 | +| 消费场景 | **仅会话内图库**(浏览/删除);笔记内联消费留待下版 | |
| 28 | +| 手动框选表面 | **屏卡全帧图上框选**(复用屏卡流与 full 图;不碰实时链路) | |
| 29 | +| 自动范围 | **结构三类 + Image 区域**(Image 需 `diagram_likeness` 过滤防照片/装饰误收) | |
| 30 | +| 实现方案 | **方案 A+**:批量时机 + 屏内多帧选优(详见 §三) | |
| 31 | + |
| 32 | +## 三、方案对比与性能结论 |
| 33 | + |
| 34 | +| 方案 | 内容 | 权衡 | |
| 35 | +|------|------|------| |
| 36 | +| A:纯批量 | 停止后对屏卡代表帧(first_seen)重跑版面分析 → 裁剪入库 | 架构最简;质量上限=屏卡帧 | |
| 37 | +| **A+(裁决)** | A + 裁剪源换成**屏时间窗内多归档帧中清晰度最高帧**(pick_sharpest 纯函数) | A 的复杂度拿 B 的大部分质量 | |
| 38 | +| B:在线采集状态机 | 实时链路挂 StructureTracker:区域跟踪 + 逐帧清晰度评估 → 最优帧裁剪 | 增量 CPU 小(区域匹配微秒级、清晰度评估复用边缘网格、编码每区域仅一次),但**状态机复杂度与实时链路回归风险大**(与 ScreenTracker/region_tracker 并存;v0.7.5 刚根治停止残留类问题);且屏卡代表帧已有 novelty 门控(动效中间帧本就不会成为屏卡帧),B 的质量优势被削弱 | |
| 39 | + |
| 40 | +**性能结论(用户提问)**: B 的增量 CPU 负载很小(对比 OCR 数百 ms/次且已被变化检测+冷却门控,B 每帧增量几十微秒),真正的成本是状态机复杂度与实时链路回归风险 → 不选 B。 |
| 41 | + |
| 42 | +## 四、设计规格 |
| 43 | + |
| 44 | +### 4.1 数据层 |
| 45 | + |
| 46 | +**新表 `session_structure_images`**(`ensure_table` 幂等迁移,ADR-014 先例): |
| 47 | + |
| 48 | +| 列 | 说明 | |
| 49 | +|----|------| |
| 50 | +| `id` | 主键 | |
| 51 | +| `session_id` | 会话(查询主路径,建索引) | |
| 52 | +| `screen_id` | 所属屏(NULL=旧数据无屏)——为将来笔记按屏消费留锚点 | |
| 53 | +| `kind` | `table` / `formula` / `code` / `image` / `manual`(字符串枚举,**不动** `RegionKind`——版面分析模块零改动) | |
| 54 | +| `bbox` | JSON `{x,y,w,h}` 帧坐标 | |
| 55 | +| `source_ts_ms` | 裁剪源帧时间戳 | |
| 56 | +| `crop_path` | `struct/{ts}.webp` 相对路径 | |
| 57 | +| `source` | `auto` / `manual` | |
| 58 | +| `created_at` | 入库时间 | |
| 59 | + |
| 60 | +**存储**:`image_store` 新增 `struct/` 命名空间——与 `crop/`(精修中间产物)**语义分离**:`struct/` = 持久化结构图(图库消费),`crop/` = refine 候选。缩略图同步生成(复用现有缩略管线)。 |
| 61 | + |
| 62 | +**预算**:独立桶 `STRUCT_BUDGET_AUTO`(常量 80/会话,仅限自动捕获);**手动框选不设限**(用户主动行为不被预算驱逐)。auto 耗尽即停止本会话后续自动捕获(手动不受影响)。 |
| 63 | + |
| 64 | +**去重**:复用 `same_image` 双指纹(aHash+dHash,REQ-067 先例)——同屏同区域多帧候选只存一张;批量重跑幂等。 |
| 65 | + |
| 66 | +### 4.2 自动捕获(批量任务) |
| 67 | + |
| 68 | +**触发**:会话停止后自动跑(与 REQ-159 结构精修同节奏);图库提供"重新捕获"按钮可重跑(去重保证幂等)。 |
| 69 | + |
| 70 | +**管线**(新模块 `structure_capture.rs`,纯函数核心 + 命令胶水,单文件 ≤300 行): |
| 71 | + |
| 72 | +``` |
| 73 | +capture_session_structures(session_id): |
| 74 | + 屏列表(screens 派生查询,屏卡体系产出) |
| 75 | + 每屏: |
| 76 | + ① 帧候选:full/ 目录中时间戳 ∈ [first_seen, last_seen] 的归档帧 |
| 77 | + (每屏采样上限 8 帧,超出均匀抽样——bound 解码成本) |
| 78 | + ② pick_sharpest(candidates) → 最清晰帧(边缘能量评分,灰度网格复用 frame_features) |
| 79 | + ③ grid_from_bgra(复用)→ analyze_layout(复用) |
| 80 | + ④ 区域过滤: |
| 81 | + - table/formula/code → 直接候选(is_structural) |
| 82 | + - image → diagram_likeness(region_grid) ≥ 阈值 → 候选 |
| 83 | + - text / unknown → 跳过(text 走 OCR 线性文本;unknown 归 V1.0 AI 补缝) |
| 84 | + ⑤ 白边裁剪(image_crop 复用)→ WebP → struct/ + thumb/ |
| 85 | + ⑥ same_image 去重 → 预算检查 → 入库 |
| 86 | +``` |
| 87 | + |
| 88 | +**`diagram_likeness(region_grid) -> f32`**(新纯函数,阈值 0.5 起步真机调参): |
| 89 | +- 边缘密度:框线/箭头结构多(复用边缘网格概念,frame_features 产出) |
| 90 | +- 面积占比:区域面积 / 屏面积 ≥ 阈值(照片贴图与结构图粗分) |
| 91 | +- 灰度方差:非纯色(防纯色装饰块误收) |
| 92 | +- 三特征加权综合;合成网格单测(流程图样/照片样/纯色样/阈值边界) |
| 93 | + |
| 94 | +### 4.3 手动捕获(屏卡框选) |
| 95 | + |
| 96 | +**交互**:原料屏卡 full 图 → 「框选截取」按钮进入选择模式(`BoxSelectOverlay` 拖框)→ 松开出**确认浮层**(裁剪预览 + 保存/取消,防误触产生垃圾图)→ 保存。 |
| 97 | + |
| 98 | +**命令**:`capture_structure_manual(session_id, screen_id, x, y, w, h)`(归一化 0-1 坐标): |
| 99 | +1. 解析屏卡 `image_ref` full 图;缺失 → 明确错误(前端禁用按钮并提示"该屏无图像") |
| 100 | +2. 归一化 → 像素坐标;越界自动钳制;<32×32px 拒绝 |
| 101 | +3. **按用户框选原样裁剪**(不做白边裁剪——用户意图优先)→ `struct/` + 缩略图 |
| 102 | +4. 入库:`kind=manual`,`source=manual`,`source_ts_ms=屏 first_seen`,bbox=裁剪框 |
| 103 | +5. 不设预算上限 |
| 104 | + |
| 105 | +### 4.4 会话内图库 UI |
| 106 | + |
| 107 | +**`ImageGallery.tsx` 扩展**(现 105 行,新增独立组件保持单文件 ≤300 行): |
| 108 | +- 新组件 `StructureImageSection.tsx`:结构图网格——kind 徽标(表格/公式/代码/图结构/手动)+ source 徽标(自动/手动)+ 时间 `MM:SS` + 屏号 + 删除按钮 + 「重新捕获」按钮 + 空态提示 |
| 109 | +- 命令:`list_session_structure_images(session_id)` / `delete_structure_image(id)`(删记录+删文件——文件仅被本表引用,可安全删)/ `capture_session_structures(session_id)`(重跑) |
| 110 | +- 大图预览与参考图共用(见 4.6) |
| 111 | + |
| 112 | +### 4.5 修复①:会话列表没有全选框 |
| 113 | + |
| 114 | +**现状**:`SessionListPanel` 有逐项勾选 + 批量操作栏(已选 N/批量转/批量删除/取消),无全选。 |
| 115 | +**设计**:批量操作栏最左加「全选」复选框,**口径 = 当前筛选视图(filtered 集合)**: |
| 116 | +- 三态:全部选中(checked)/ 部分选中(indeterminate)/ 未选中 |
| 117 | +- 点击选中 → `selected` = 当前 filtered 全部 id;再点 → 清空 |
| 118 | +- 列表视图与课程分组视图共用(filtered 口径一致) |
| 119 | +- 段搜索命中视图批量栏隐藏(现状)→ 全选框自然不出现 |
| 120 | +- 纯前端本地状态(selected 已是本地 Set),**零后端改动** |
| 121 | + |
| 122 | +### 4.6 修复②:参考图片无法查看详情 |
| 123 | + |
| 124 | +**现状**:`ImageGallery` 缩略图无任何点击处理,无法查看大图。 |
| 125 | +**设计**:新组件 `ImagePreviewOverlay.tsx`: |
| 126 | +- 点击缩略图 → 遮罩 + 大图(`contain` 适配窗口) |
| 127 | +- 信息栏:相对路径 + 时间戳 + 删除按钮 |
| 128 | +- ESC / 点击遮罩关闭 |
| 129 | +- 参考图集与结构图区段共用(一处实现两处消费) |
| 130 | + |
| 131 | +### 4.7 降级链(本地优先铁律) |
| 132 | + |
| 133 | +1. 新会话(screen_id + full 图 + 版面信息)→ 全能力自动捕获 |
| 134 | +2. 旧会话无 screen_id → 屏列表空 → 自动捕获跳过(图库空态);手动框选需屏卡有图(无图禁用+提示) |
| 135 | +3. 无 full 归档帧(图集未开)→ 该屏自动跳过(不阻断其他屏) |
| 136 | +4. 版面分析空/失败 → 该屏跳过 |
| 137 | +5. 全部失败 → 图库空态 + 手动框选仍可用(手动不依赖版面分析) |
| 138 | + |
| 139 | +### 4.8 测试(AAA,纯函数优先) |
| 140 | + |
| 141 | +- `diagram_likeness`:流程图样/照片样/纯色样/阈值边界(合成网格,layout_analyzer_tests 先例) |
| 142 | +- `pick_sharpest`:多帧选最大/空列表/全零 |
| 143 | +- 批量管线:mock 屏+帧 → 候选集/去重/预算耗尽停止/幂等重跑 |
| 144 | +- 手动命令:越界钳制/最小尺寸拒绝/无 image_ref 错误 |
| 145 | +- DB:ensure_table 幂等/CRUD/旧库兼容 |
| 146 | +- 前端:框选归一化坐标纯函数 + 真机手动清单(Vitest 基建维持 v0.8.0 裁决) |
| 147 | + |
| 148 | +## 五、验收标准 |
| 149 | + |
| 150 | +- [ ] 重跑真实会话:停止后自动捕获表格/公式/代码入图库;PPT 流程图被捕获;照片/装饰**不**误收(阈值调参) |
| 151 | +- [ ] 图库:结构图区段徽标/时间/来源/删除生效;「重新捕获」幂等 |
| 152 | +- [ ] 手动:屏卡框选 → 预览确认 → 入库;无图屏按钮禁用+提示 |
| 153 | +- [ ] 修复①:全选框三态正确(当前筛选视图口径),批量转/批量删不受影响 |
| 154 | +- [ ] 修复②:参考图/结构图点击均大图预览,信息栏/删除/ESC 关闭正确 |
| 155 | +- [ ] 旧会话零回归;`cargo test` + `cargo clippy` 全绿;前端构建通过 |
| 156 | + |
| 157 | +## 六、需求登记(REQ-182~187,详见需求池) |
| 158 | + |
| 159 | +| REQ | 内容 | 优先级 | |
| 160 | +|-----|------|--------| |
| 161 | +| REQ-182 | 结构图自动捕获:批量任务(停止后触发+图库可重跑)——屏内选优帧 → 版面分析 → table/formula/code 直收 + Image 过 diagram_likeness → 白边裁剪入库 | P1 | |
| 162 | +| REQ-183 | 结构图持久化:session_structure_images 新表 + struct/ 命名空间与缩略图 + 独立预算(auto 80/会话,manual 不限)+ same_image 去重 | P1 | |
| 163 | +| REQ-184 | 手动结构图截取:屏卡全帧图框选(BoxSelectOverlay + 确认浮层)→ capture_structure_manual(归一化/钳制/最小尺寸拒绝) | P1 | |
| 164 | +| REQ-185 | 会话内结构图库:ImageGallery 扩展 StructureImageSection(kind/source 徽标 + 时间 + 屏号 + 删除 + 重新捕获) | P1 | |
| 165 | +| REQ-186 | 修复:会话列表全选框(当前筛选视图口径 + indeterminate 三态) | P2 | |
| 166 | +| REQ-187 | 修复:参考图片详情查看(ImagePreviewOverlay 大图预览,参考图/结构图共用) | P2 | |
| 167 | + |
| 168 | +## 七、明确不做(本版裁决) |
| 169 | + |
| 170 | +- **笔记内联消费**(下版;表已留 screen_id 锚点,配图链路 REQ-160 已就绪) |
| 171 | +- **在线采集状态机**(方案 B——复杂度/回归风险大于收益) |
| 172 | +- **手动类型标注**(流程图/思维导图选择器——YAGNI) |
| 173 | +- **AI 语义重建**(V1.0,REQ-056/058 既规划;本版图像即最终产物) |
| 174 | +- **导出/右键另存**(图库可删除已够,导出随笔记消费下版评估) |
| 175 | +- **diagram_likeness 模型化**(规则版先行,模型版属 V1.0 版面模型组范畴) |
0 commit comments