Repository navigation
Releases: wahonet/WSC3D
Release list
v0.9.0
v0.9.0 — 数据可信度加固
v0.8.0 之前一直在加功能,到这一版功能链基本齐了。v0.9.0 不再扩功能,回头把"数据可信度"和"工程地基"做扎实:每条标注能不能进训练池、为什么不能、怎么一键修;AI 兜底产出的候选不再混在真神经网络置信度里;纯函数有了回归网,不会再改个小地方就出隐蔽 bug。
一句话:从"功能验证型"转向"数据质量型"。
完整发布说明:https://github.com/wahonet/WSC3D/blob/main/docs/RELEASE_NOTES_v0.9.0.md
逐步工作日志:https://github.com/wahonet/WSC3D/blob/main/docs/WORK_LOG_v0.9_reinforcement_2026-07-01.md
修复
- import-md 不再静默失效:
/api/iiml/:stoneId/import-md(从结构化档案导入标注)之前因为 catalog 不再解析 Markdown,导入 0 条却不报错;现在直接解析档案,找不到时明确抛metadata_not_found。
改进
- 训练就绪度面板:编辑任意标注,顶部实时显示"能否进训练池 / 卡在哪一项 / 一键修复",标注时就能修,不用等导出才发现大批失败。
- 列表批量修复:多选标注后批量设类别 / 审核状态 / 质量 / 训练角色。SAM 一批产出 20 条 candidate,几下就升成可训练状态。
- AI fallback 显式分级:SAM/YOLO 兜底的轮廓候选显式标
weak+ fallback 徽章,不再用假置信度(0.62)混在真神经网络候选里,避免污染训练集。 - SAM image embedding 缓存:同一块石头多次 prompt 只算一次 embedding,批量标注明显变快。
- 对齐重投影误差反馈(保存 4 点对齐时状态条显示残差)。
- catalog 自动失效:加新模型自动重建列表,不再需要手动
POST /api/scan/refresh。
工程地基
- 单元测试底盘:之前零测试。这一版用
node:test+ tsx(零新依赖)加了 63 个用例,覆盖训练池准入 11 项约束、4 点单应性矩阵 roundtrip、COCO 70/15/15 划分的防泄漏不变量、IIML frame 迁移、SAM3 概念词映射。 - 依赖分层:
requirements.txt默认 CPU(MobileSAM 本就跑 CPU),GPU 用户换requirements-cu128.txt给 SAM3 提速;消除了 requirements / pyproject 长期的版本矛盾。 cloneDoc→ 原生structuredClone;App.tsx 抽出 SAM3 概念词映射纯函数;修了 main.py 端口注释笔误。
文档与许可
- 采用 木兰宽松许可证第2版(MulanPSL-2.0),详见 LICENSE。
- README 重写:口语化,每个模块(浏览 / 拼接 / 标注)讲清功能、作用和实现方式。
- 新增 v0.9.0 发布说明与工作日志;归档了内部过程文档(ROADMAP / THINKING / 旧 worklog 等)。
验证
npm run typecheck 通过 · npm test 63/63 全绿 · Python py_compile 通过
WSC3D v0.8.0
WSC3D v0.8.0 — 图谱 UI 修缮 · 资源独立 tab · 三维生成正射图 · 多资源画布切换 · 跨资源坐标变换 · .hpsml 解包 · 正射图 1:1 对齐与跨资源 SAM/YOLO(J 补丁)
发布日期:2026-05-04
对应计划:v0.7.0 验收反馈修缮 + v0.8.0 M4 多资源架构落地
上一发布:v0.7.0— 紧急修复 · 图谱完善 · 多解释 UI · AI 加深 · 多资源 · .hpsml 包
v0.7.0 浏览器端验收那轮的反馈集中在图谱 UI 挤、"资源"应该独立 tab、以及
没有原图 / 拓片时想用三维模型生成一张正射图当底图。把这波修掉后,顺势把
v0.8.0 规划的 M4 多资源架构三条线也落了地:多资源画布切换、跨资源
坐标变换(数据模型)、.hpsml 研究包解包导入。
这一版的核心是:这块画像石除了三维模型和 pic/ 下的原图之外,现在也能用
自己生成的正射图、手工注册的拓片 / 法线图 / RTI / 点云作为底图来标注,
还能把别人(别的研究者 / 别的机器)导出的 .hpsml 一键导进来。
工作日志:WORK_LOG_post_v0.7.0.md。
1. 图谱 UI 修缮(H1)
v0.7.0 的图谱 tab 被反馈:4 行 chip(布局 / 着色 / 中心性 / 类别)字太大挤换行;
PageRank 写英文没看懂;右侧 230px 排行榜侧栏把 canvas 挤窄。
这一版的调整:
- 中心性算法中文化:权威度(PageRank)/ 邻居数(Degree)/ 桥梁度(Betweenness)
/ 接近度(Closeness)。PageRank 不再露英文;hint 补 "Google PageRank 同款算法" - chip 行 4 → 2:第一行 "布局 + 着色 + 中心";第二行 "中心性 + 类别 + 来源"。
每段之间加.knowledge-graph-filter-divider细竖线视觉分组 - 排行榜从侧栏挪到下方:
.knowledge-graph-stage改flex-direction: column,
canvas 占整行min-height: 380px;排行榜改横向滚动卡片(每张 172px) - 群组规模 chip 并入排行榜 head:不再占独立区块;head 加
shortHintFor(kind)
简短提示(如 "被高权重邻居指向 → 综合权威") - 整体字号统一缩小:chip 从 11.5 → 10.5px,padding 缩;
.knowledge-graph-tab
min-height 360 → 520px 让 canvas 更舒展
2. 资源独立 tab + 三维模型生成正射图(H2 + H3)
2.1 "资源" tab
AnnotationPanel.TabKey 加 "resources"(Layers 图标 + 中文"资源")。
原本嵌在 ListTab 顶部的 ResourcesEditor 移到这个新 tab 下,可以占满面板高度。
2.2 ResourcesEditor 重写:3 个 section
- 从三维模型生成正射图:4 个方向 chip(正面 / 背面 / 顶面 / 底面)+
"生成正射图"按钮 - IIML 资源条目:列出
doc.resources[],每条支持预览图像(160px max-height
object-fit: contain)/ 删除 / 新标签页打开 - 后端已落盘:列出
data/stone-resources/{stoneId}/下实际文件;未关联
的一键"关联"到 IIML resources[]
2.3 正射图生成管线
前端 frontend/src/modules/annotation/orthophoto.ts(新建):
- 独立 offscreen Three.js 渲染器:
WebGLRenderer+document.createElement("canvas") - GLTFLoader 加载模型 → 算 AABB →
OrthographicCamerafrustum 正好裹住模型 + 5% 留白 - 4 种视图方向(front / back / top / bottom)
- 光照:AmbientLight 0.75 + DirectionalLight 1.0 斜上 45°(拓片摄影棚单灯效果)
- 背景 3 档:light(近拓片纸色 #efe7d8,默认)/ dark / transparent
- 输出 PNG blob + 像素尺寸 + 模型 AABB 尺寸 + frustumScale + view
- 所有 Three.js 资源在 finally 里 dispose +
forceContextLoss()防 WebGL context 泄漏
后端 backend/src/server.ts:
GET /api/stones/:id/resources:列出data/stone-resources/{stoneId}/下所有
落盘图像POST /api/stones/:id/resources:接收 PNG(Content-Type: image/png原始二进制
或 JSON{ type, imageBase64 }),落盘为{type}-{timestamp}.png- 静态托管
/assets/stone-resources/ - body size 25MB(3072px 长边 PNG 大约 5-10MB)
生成后自动:generateOrthoImage → uploadStoneResource → onAddResource 加进
IIML → refreshServerResources 刷新后端列表。
3. 多资源画布切换(I1)
SourceImageView 新增 imageUrl?: string props:默认走 /ai/source-image/{stoneId}
(pic/ 原图),传了就用它(任意 doc.resources 里的 image 类资源 URI)。
AnnotationWorkspace 新增"资源切换" segmented UI,高清图模式下显示在
source-switch 与 layer-switch 之间:
- 默认"原图"(pic/ 走
/ai/source-image/) doc.resources[]里 Orthophoto / Rubbing / NormalMap / LineDrawing /
OriginalImage / RTI / Other 类型的资源都会自动列成 chip- chip 文案按类型 + 方向生成("正射·正" / "拓片" / "法线" / ...)
- 切到非 pic/ 资源时强制禁用 Canny 线图叠加(后端 canny 管线只处理 pic/ 原图)
使用场景:生成正射图后切到"正射·正"底图,在上面继续标注;或手工注册
外部拓片 URI 后切到"拓片"底图做对照研究。
4. 跨资源坐标变换(I2)
数据模型层先行,为 v0.9.0 的画布跨资源投影做准备。
types.ts 新增 IimlResourceTransform 联合类型:
type IimlResourceTransform =
| {
kind: "orthographic-from-model";
view: "front" | "back" | "top" | "bottom";
modelAABB: { width: number; height: number; depth: number };
pixelSize: { width: number; height: number };
frustumScale: number;
generatedAt?: string;
}
| {
kind: "homography-4pt";
controlPoints: Array<{ model: [number, number]; image: [number, number] }>;
referenceResourceId?: string;
}
| {
kind: "affine-matrix";
matrix: number[];
referenceResourceId?: string;
};IimlResourceEntry.transform 字段可选保存变换。
正射图生成时自动填入 transform: { kind: "orthographic-from-model", view, modelAABB, pixelSize, frustumScale }。这样 modelBox UV ↔ 正射图 UV 就有了
精确可算的对应关系。
ResourcesEditor 卡片上新增 .resources-item-transform 金绿色提示条,显示
"正射投影 · 正面 · AABB W×H · frustum 1.05× · 像素 W×H"。
画布投影实装留 v0.9.0:v0.8.0 只把跨资源元数据铺好,画布渲染时暂仍按
原 frame 显示(不做跨资源投影),避免引入画布层 bug 影响主流程稳定性。
5. .hpsml 解包导入(I3)
backend/src/services/hpsml.ts 新建 importHpsmlPackage(root, config, getCatalog, payload, options):
- 校验:
format === "hpsml"+formatVersion(不同版本告警继续尝试) - 解 stoneId 优先级:
options.stoneId>context.stone.id>
iiml.documentId的前缀({stoneId}:iiml) - IIML 主体:直接走
saveIimlDoc(完整 ajv 校验,写入
data/iiml/{stoneId}.iiml.json) - 拼接方案:写入
data/assembly-plans/;冲突时生成新 id +
importedFromHpsml: true标记 - 冲突策略
options.conflictStrategy:"overwrite"(默认):直接覆盖本机已有"skip":若本机已存在则跳过 IIML 部分
后端端点:POST /api/hpsml/import?stoneId=...&conflict=overwrite|skip
(body = 完整 .hpsml JSON)
前端:
client.ts加importHpsmlPackage(payload, options)+HpsmlImportSummary类型AnnotationPanelListTab 下载区加"导入 .hpsml"按钮App.handleImportHpsml:用隐藏<input type="file" accept=".json,.hpsml">
触发文件选择,解析 JSON 后调 API;若导入的是当前stoneId,自动重新拉 IIML
让画布刷新
返回 summary:
{
"stoneId": "asset-29",
"imported": {
"iiml": true,
"annotations": 42,
"relations": 18,
"processingRuns": 6,
"resources": 3,
"assemblyPlans": 2
},
"skipped": { "iiml": false, "assemblyPlans": 0 },
"warnings": []
}6. commit 时间线
8cb7236 feat(annotation+backend): I1+I2+I3 多资源画布切换 + 跨资源坐标变换 + .hpsml 解包导入
8fb2583 feat(annotation+backend): H1+H2+H3 图谱 UI + 资源 tab 独立 + 三维模型生成正射图
ea995dc docs(v0.7.0): release notes + README + ROADMAP + 工作日志收尾
H 和 I 共 2 次 feat commit + 1 次 docs 收尾 commit(v0.7.0 → v0.8.0 共 3 次)。
7. 数据兼容
- 历史 IIML 文档没
resources[*].transform字段:按undefined处理,UI 容错显示 - 历史 IIML 文档没
resources[*].type === "Orthophoto":跨资源切换 UI 只显示
已存在的类型,不影响主流程 .hpsmlv0.1.0 formatVersion:导入时校验;未来 formatVersion 变化时先告警
再尝试兼容导入data/stone-resources/{stoneId}/目录不入库(.gitignore已有data/但
该子目录按需建立;多机协作时通过 .hpsml 包或单独 rsync)
8. 验收要点
进标注模式后依次试:
- 图谱 UI:图谱 tab → 布局 / 着色 / 中心 chip 一行完整显示不换行;
中心性下方是 "权威度 / 邻居数 / 桥梁度 / 接近度";canvas 占整行变大;
排行榜在 canvas 下方横向滚动 - 资源 tab:右侧 panel 应有 "资源" tab,点开看到 3 个 section
- 生成正射图:资源 tab → 选 "正面" → 点 "生成正射图" → 等 3-8 秒 →
IIML 资源条目区应新增一条 Orthophoto,缩略图显示生成的正射图;卡片下方
应有金绿色 "坐标变换 · 正射投影 · 正面 · AABB ... · frustum 1.05× · 像素 ..."
提示条 - 多资源画布切换:标注模式 → 切到高清图 → canvas 右上角 source-switch
下方应出现 "底图 原图 正射·正" 的资源切换条 → 点 "正射·正" → 画布显示
正射图;+线图 按钮自动置灰 - .hpsml 导入:先从 v0.7.0 导出的 .hpsml 文件 → 列表 tab 下载区点 "导入
.hpsml" → 选文件 → status 显示 "已导入 .hpsml(stoneId=xxx):IIML 写入、
标注 N / 关系 N / 拼接方案 N" → 若是当前画像石,画布自动刷新 - 后端已落盘刷新:资源 tab 第 3 个 section 应列出生成过的正射图文件;
点 "刷新" 应扫描data/stone-resources/{stoneId}/重新列出
9. J 补丁:正射图 1:1 对齐 + 跨资源 SAM / YOLO
收到用户反馈"生成的正射还有白边、SAM / YOLO 只能跑 pic/、正射和 3D 模型标注
不同步"之后在当天补的 J 补丁。核心思路是让正射图从生成开始就严格对齐 3D
模型 AABB,这样正射图 UV 数值上等于 modelBox UV,跨资源标注同步不需要再做
数学变换。
9.1 正射图 frustumScale 1.05 → 1.0
frontend/src/modules/annotation/orthophoto.ts:生成 frustum 从"AABB × 1.05
留白"改为"严格贴 AABB"。生成的 PNG 紧贴模型边缘,没有白边- 返回值增加
equivalentToModel: boolean;view=front + frustumScale=1.0 满足
时为 true,表示该正射图图像 UV 与 modelBox UV 完全 1:1 对应 IimlResourceTransform.orthographic-from-model也加equivalentToModel?: boolean
字段跟随持久化;老数据(没有该字段)通过 view=front + |frustumScale-1|<1e-3
的兜底判据也能识别为等价
9.2 SAM / YOLO 后端接 imageUri
ai-service/app/sam.py:新增sam_segment_by_uri(uri, prompts_uv)。URI 解析
支持/assets/stone-resources/...→<repo>/data/stone-resources/...本地
路径反解;不走 HTTP,不依赖 backend 在线ai-service/app/yolo.py:对应加yolo_detect_by_uri(uri, ...)ai-service/app/main.py:SamRequest/YoloRequestschema 加imageUri
字段;路由优先级 imageUri > stoneId > imageBase64- 这条新路径的坐标系是"图像 UV";当图像 UV 与 modelBox UV 等价时,前端直接
当 model frame 坐标用,不需要额外变换
9.3 前端 AI 调用随资源走
frontend/src/api/client.ts:runSamSegmentationBySource/runYoloDetection
参数加imageUri?: string;SAM 路径要求 imageUri 或 stoneId 至少给一个frontend/src/modules/annotation/sam.ts:refineBBoxWithSam和
requestSamCandidateWithSource加imageUri参数;传了就走 imageUri 分支frontend/src/modules/annotation/AnnotationCanvas.tsx:新增activeImageUri
prop;SAM 手动 prompt 提交时透传过去frontend/src/modules/annotation/AnnotationWorkspace.tsx:新增
onActiveImageResourceChange回调,把当前底图资源(id / uri / type /
equivalentToModel)告诉 App 层,让 YOLO 批量扫描 / SAM 精修都能拿到正确的
imageUrifrontend/src/App.tsx:handleSubmitYoloScan读activeImageResource.uri作为 YOLO 输入;候选
frame按 equivalentToModel 决定(等价时记 model,否则跟随 sourceMode)handleRefineWithSam从annotation.resourceId反查资源 URI,在原资源上
跑 SAM 精修,不错位到 pic/
9.4 跨资源标注自动同步(等价正射图)
AnnotationWorkspace新增派生状态activeResourceEquivalentToModel
(transform.equivalentToModel === true或 view=front + frustumScale≈1)effectiveSourceMode = sourceMode === "image" && activeResourceEquivalentToModel ? "model" : sourceMode:在等价正射图上,画布按 model 坐标系处理- 传给 AnnotationCanvas 的
sourceMode用 effectiveSourceMode → 在等价正射图
上新建的标注 frame="model",3D 模型视图自动能看到;反过来 model frame 的
历史标注也直接在等价正射图上显示 - UI 额外提示:等价正射图顶部有一枚绿色徽章"此图与 3D 模型坐标系已对齐 ·
标注自动双向同步"(.annotation-resource-aligned-hint样式) - 非等价资源(top/bottom/back 方向、或 frustumScale 不是 1.0 的老数据)仍按
image frame 处理,用户可走已有的 4 点单应性标定跨 frame 投影;这部分的
自动反投影留 v0.9.0(画布层按 resource.transform 投影任意资源坐标)
9.5 验收
- 生成正射图:图像紧贴模型 AABB,无白边
- 在等价正射图底图上 SAM 框选 → 候选直接出现在 3D 模型视图上(切回 3D 模型
模式可见) - ...
WSC3D v0.2.1
WSC3D v0.2.1 — 拼接模块多石拖动修复
发布日期:2026-05-03
Tag:v0.2.1
修复加入第二块画像石后,第一块 gizmo 错位、轴箭头无法响应拖动,仅中心
黄色 plane handle 表面上"还能用"的问题。
修复
- gizmo 不再随每次加石头被重置:
fitAssemblyCamera现在只在首次
加载石头时跑一次。之后加新石头会保留当前用户视角,避免相机突然平移
到合并包围盒中心,造成"屏幕中央不再对齐 gizmo 中心"的错位陷阱。 - dragging 中不再回灌 transform:新增
isDraggingRef,避免 React
state 同步对正在被拖动的对象做applyTransform,消除潜在抖动 / 位移
反弹。 - 新石头落点更友好:偏移改为基于"上一块的 X + 半宽估算",新加
画像石紧邻已有石头序列右侧,避免落点离视野太远。
提示
- 想一次性把全部石头框进视野,左侧工具栏有「重置视角」按钮(圆环箭头),
手动 fit。 - 若旧拼接方案是在错位状态下累计保存的,加载后可在面板里选中对应石块,
重新使用 gizmo 或微调按钮校准。
详细发布记录见 git log v0.2.0..v0.2.1。
WSC3D v0.2.0
WSC3D v0.2.0 — 标注模块
发布日期:2026-05-03
Tag:v0.2.0
本次发布将标注模块从「图层 + 标注」两层模型简化为「一标注一图层」模型,
并完善了浏览 / 拼接 / 标注三大模块的能力。
标注模块
- 标注坐标改为
modelBox归一化空间(u, v) ∈ [0, 1]²,StoneViewer暴露 4 角屏幕投影。
用户在 2D 模式下平移 / 缩放视图时,所有标注会随相机自动跟随,无需手动调整。 - 工具集精简为 选择 / 矩形 / 圆 · 椭圆 / 点 / 钢笔 五件,
矩形与椭圆需拖动出尺寸(≥ 4 像素)才会创建,避免误点产生空标注。 - 创建后自动切回选择工具并选中新建标注,进入"草稿"状态:
- 右侧详情面板显示「标签 / 备注 / 确定 / 取消 / 删除」。
- 草稿外的标注同样支持随时重命名、隐藏、锁定、删除。
- 不再有独立的 Layer 概念。每条标注自带
color/visible/locked:- 锁定后,整体拖动与四角 handle 都不可用,相当于把这一条标注冻结。
- 隐藏后画布上不再渲染该条标注。
- 标注列表与详情合并到单一面板,去掉了原有的 tab 切换。
浏览 / 拼接
- 浏览模式不再渲染标注覆盖层,标注内容仅在标注工作区可见、可编辑。
- 浏览/拼接其余功能保持原状(视角骰子、测量、拼接方案保存等)。
数据兼容
- 进入旧 IIML 文档时自动迁移:补齐每条标注的
visible / locked / color,剥离过时的layers字段。 - 颜色按调色板循环分配,老用户首次保存后会失去图层名称信息,但标注本体不丢。
工程
- 移除了原本未启用的 SAM / YOLO / Canny 入口与"导入档案骨架 / 导出 IIML"按钮,专注手工标注。
- AI 子服务(
ai-service/)保留接口,留待 M3 重新接入。 - 完善
README.md与
docs/ROADMAP.md,
明确当前能力与近 / 中 / 远期工作计划。
已知问题
- 浏览 / 拼接模式下没有标注气泡叠加,将在 M2 加上。
- 钢笔工具尚未支持贝塞尔控制柄。
- 主 chunk > 1MB,按模块做动态 import 的代码分割留待 M2。
完整下一步计划见 docs/ROADMAP.md。
V0.3.0: feat(annotation): AI 标注闭环 · 多源底图 · 4 点对齐校准
WSC3D v0.3.0 — AI 标注闭环 · 多源底图 · 4 点对齐校准
发布日期:2026-05-04
对应计划:M3 第一波(见ROADMAP.md第 2 节)
上一发布:v0.2.2— 标注模块 ICON 化与工程小修
本次发布是标注模块自 v0.2.0 重构以来最大的一次能力扩展,三件大事:
- AI 标注闭环可用:SAM 候选从"能出"升级到"能用",修了致命的坐标系翻转,
引入了高清图直读路径,候选审阅支持多选合并; - 多源底图:标注画布可以在 3D 模型 与 画像石高清原图 之间任意切换,
高清图模式下 SAM 候选与显示天然对齐,识别精度大幅提升; - 4 点单应性对齐校准:用户在两个底图各点 4 对对应点,标注就能在两个坐标系
之间双向投影 —— 在图上画的标注切回 3D 模型也能看到,反之亦然。
同时把鼠标交互在两种底图上拉齐:滚轮缩放 + 中键 / 右键拖动,再无差异。
1. 标注模块 · AI 闭环
1.1 SAM 高清图路径修复(关键 bug)
旧高清图路径下 SAM 返回的 polygon 在画布上 上下颠倒。根因是前后端 v 轴方向
约定不一致:前端 screenToUV / uvToScreen 用 v 向下(与图像/屏幕坐标一致),
后端 _uv_to_pixel_prompt 与 _flip_polygon_to_uv 却假设 "modelBox v 向上",
入口 / 出口各做一次 y 翻转 —— 结果是点击点送到原图错处分割,分割结果又被反向
画回画布。
修复:删除后端两处 y 翻转,统一约定 "前后端 UV 都 v 向下"。前端注释和 API 文档
同步更正。
1.2 高清图直读端点
新增 GET /ai/source-image/{stone_id}:
- 在 ai-service 里读
pic/下匹配stone_id数字前缀的 tif / png / jpg - PIL 解码后按长边 4096 LANCZOS 缩放,落盘缓存到
ai-service/cache/source/{n}_max{m}.png - 第二次访问直接命中缓存(毫秒级)
- 原图 mtime 比缓存新会自动重新转码
意义:浏览器原生不支持 tif,又不可能把 178 MB 原图塞进 base64;这条路径让前端
可以 <img src="/ai/source-image/asset-29"> 直接渲染高清原图。
1.3 候选合并(polygon union)
引入 polygon-clipping(35 KB,专做 2D 多边形布尔运算)。在候选 / 列表两个 tab
都新增 checkbox 多选:
- 选中 ≥ 2 个候选 → 顶部出现"合并选中(N)"按钮
- 几何上对所有源 polygon 做 union,只保留外环(丢孔洞),满足"只要最外面的边缘"
的诉求 - 合并后的 reviewStatus 用"最保守原则":任一源是候选 → 结果是候选;否则跟随
第一个源的状态(避免已 approved 的标注合并后被打回未审) - 跨 frame(model + image)选中会被拒绝并提示,避免坐标系混淆
针对 SAM 经常把人物身体识别成两片的场景效果显著 —— 选两片合并即得完整轮廓。
1.4 候选审阅小改
- 候选卡片左上加 checkbox +
is-selected高亮 - 列表 tab 也复用同一套合并工具条,已 approved 标注合并不再走候选审定流程
2. 标注模块 · 多源底图
2.1 高清图视图(SourceImageView)
- 用
<img>+ 自维护的ViewState { scale, offsetX, offsetY }渲染 PNG - 滚轮:以光标为中心缩放(fit×0.5 ~ fit×30)
- 中键 / 右键拖动:平移
- 父级
fitToken递增(工具栏"重置视角"按钮):复位到 contain-fit 状态 - 窗口尺寸变化时不强制重置 viewState,避免用户调好的视角被 ResizeObserver 弄丢
- 始终向
AnnotationCanvas输出当前 transform 后的 4 角 → 标注 UV 坐标系就是
这张图自身的归一化坐标
2.2 工作区切换 UI
AnnotationWorkspace 持有 sourceMode: "model" | "image" 状态,画布右上角浮动
segmented 切换条;切到高清图时 StoneViewer 卸载、SourceImageView 挂载(共享
同一个 ScreenProjection 协议,AnnotationCanvas 不感知底图来源)。
第一次切到高清图模式有 1~3 秒解码 + 缓存写盘的等待,之后秒开。
3. 标注模块 · 4 点对齐校准
3.1 数据模型
IimlAnnotation加可选frame: "image" | "model",缺省视为"model",向后兼容IimlDocument.culturalObject.alignment持久化标定结果:controlPoints[]
存 4 对{ modelUv, imageUv };version / calibratedAt / calibratedBy记录元信息- 后端 IIML schema 已经是
additionalProperties: true,新字段无破坏性落盘
3.2 几何核心(homography.ts)
solveHomography(src, dst):4 点 DLT 构造 8×8 线性方程组 + 高斯消元(带主元)
求 3×3 单应性矩阵;选择 8 元(h[8]=1)而非 SVD —— 我们标定的是大致正向矩形,
浏览器里写稳定 SVD 不划算applyHomography(H, point):齐次坐标投影 + 归一化invertMat3:3×3 求逆(adjugate / det)buildAlignmentMatrices(alignment):从 IIML alignment 一步算出双向矩阵
3.3 跨 frame 渲染
AnnotationCanvas 收到 sourceMode + alignment,每条标注按 frame === sourceMode
决定渲染策略:
| annotation.frame | sourceMode | alignment | 渲染 |
|---|---|---|---|
| 与 sourceMode 同 | — | — | 实色实线,可拖动 / 改尺寸 |
| 与 sourceMode 异 | — | 已校准 | 稀疏虚线 + 半透明(投影态),仅可点选 |
| 与 sourceMode 异 | — | 未校准 | 跳过;画布顶部居中提示"有 N 个标注未对齐" |
跨 frame 标注暂不支持就地拖拽 / 改尺寸 —— 避免反向解算坐标的复杂度,用户切回
原 frame 编辑即可。
3.4 标定流程
工具栏新增 Crosshair 按钮(已校准时右下角青色圆点提示),点击进入"乒乓式"
4 对点采集:
- 自动切到 3D 模型,提示"在 3D 模型上点第 1/4 个特征点"
- 收满 4 个后自动切到高清图,让用户点对应位置
- 8 个点齐了进入 review,画布同时显示当前 frame 的 4 个橙色编号点 + 用现场
解算的 H 把对面 frame 的点投影过来的青色虚化点 —— 重合度即标定精度 - 底部浮窗按钮:保存对齐 / 重新采集 / 撤销上一点 / 切到对面底图 / 取消
保存即写入 IIML 并随 doc 自动持久化。再次进入标定按钮即可重新校准。
4. 视图交互一致化
历史问题:标注画布在最上层(z-index: 15),原本只在 3D 模型模式下转发滚轮和
中键 pointerdown 给 OrbitControls;右键 pan 没接,高清图模式更是完全没有 pan/zoom。
本版统一:
findStoneCanvas拆成findViewportTarget(找.three-stage canvas或
.source-image-stage)和findStoneCanvas(仅给 SAM 截图回退用)- 滚轮、中键 + 右键 pointerdown 都转发到
findViewportTarget的结果 - 3D 模型模式:右键 pan 由 OrbitControls 默认
RIGHT=PAN接住;OrbitControls
会自动 preventDefault contextmenu,不弹菜单 - 高清图模式:
SourceImageView自己实现 wheel + pointer 监听,pointer state 用
ref(不依赖 pointerId 严格匹配,兼容 AnnotationCanvas 转发的合成 PointerEvent)
最终两种底图下行为完全一致:左键标注、滚轮缩放、中键 / 右键平移、中键画
contextmenu 不弹。
5. 工程
- 新增依赖:
polygon-clipping@^0.15.7(用于候选合并) - 新增前端文件:
SourceImageView.tsx、homography.ts、merge.ts、sam.ts - ai-service 新增端点
/ai/source-image/{stone_id}+ 缓存目录ai-service/cache/ pic/、ai-service/cache/加入.gitignore,源 tif 与转码 PNG 都不进版本库- typecheck + lint + 生产 build 全绿
6. 数据兼容
- 历史标注没有
frame字段:渲染时按"model"处理,与 3D 模型模式行为一致,
老数据无感 - 历史 doc 没有
alignment:跨 frame 标注直接跳过显示并提示,行为退化为
"只显示当前 frame 的标注"
7. 已知限制
- 跨 frame 标注暂不支持就地编辑(设计取舍,详见 §3.3);用户切回原 frame 即可
- 单应性变换假设 4 点对应大致正向矩形且不严格共线;极端共线 / 退化情况下
solveHomography返回 undefined,跨 frame 渲染整体跳过 + 提示重新校准 - 候选合并目前只取每个多边形的外环;带孔(甜甜圈形状)的合并候选孔洞会被
自动填掉。汉画像石浮雕场景几乎不会有真"环形主体",不阻塞使用 - pic/ 目录下当前只有 1 张高清图(
29东汉武氏祠左石室后壁小龛西侧画像石.tif);
其它画像石需要补齐高清原图后才能用高清图模式 - 主 chunk 体积仍然 800+ KB(gzip 245 KB),引入
polygon-clipping之后未做
额外的 chunk 拆分
8. 验收要点
- SAM 候选不再上下颠倒:进标注模块 → 切到高清图 → 点 SAM 工具 → 点击图上
任意人物,候选 polygon 应严格贴合所点的图案 - 高清图模式对齐:同 1,候选轮廓应精确贴合,不再有"识别得对但位置错"的
现象 - 多选合并:候选 / 列表 tab 任一,勾选 ≥ 2 条多边形 → 顶部"合并选中"按钮
亮起 → 点击 → 原条目消失、出现合并标注(label 为"SAM 合并候选"或"合并标注") - 对齐校准:工具栏 Crosshair 按钮 → 在 3D 模型上点 4 个角 → 自动切到高清图
再点 4 个对应角 → review 阶段切回 3D 模型,看到橙色 + 青色编号点重合度
→ 保存对齐 → 工具栏按钮右下出现青色小圆点(已校准标记) - 跨 frame 显示:在高清图上画一个矩形 → 切回 3D 模型,应看到该矩形以稀疏
虚线 + 半透明形态投影到 3D 视图上的对应位置(前提是已完成 §4 的对齐) - 视图交互一致:3D 模型 / 高清图两个模式下分别测:滚轮缩放 / 中键拖动 /
右键拖动;都应该顺滑、不弹右键菜单
9. 下一步
完整规划见 ROADMAP.md。简要:
- M3 剩余:YOLO 候选检测、AI 线图(Canny / Relic2Contour)、多解释并存、
标注间关系(IIML relations)、知识图谱可视化 - M4:多资源版本切换(原图 / RTI / 拓片 / 线图)、IIIF / COCO / .hpsml 导出
本次 未自动打 git tag,等待 QA 验收后由用户决定是否打 v0.3.0 tag。