2026-05-08-02-36-12 实现STL模型切分mask

This commit is contained in:
2026-05-08 02:45:12 +08:00
parent 7b7c555321
commit 8e0e54fc3c
6 changed files with 691 additions and 5 deletions

View File

@@ -0,0 +1,65 @@
# 实现方案
开始时间2026-05-08-02-36-12
## 本次方案路径
`工程分析/实现方案-2026-05-08-02-36-12.md`
## 实现目标
在 DICOM 阅览中实现真实 STL 模型切分 mask并用单个双端点进度条控制起点/终点帧。
## 涉及文件
- `web_backend.py`
- `WebSite/src/App.tsx`
- `工程分析/经验记录.md`
## 执行步骤
1. 后端新增 STL 模型目录和缓存:
- `MODEL_DIR = web_library/_stl_models`
- `STL_MODEL_CACHE`
- 支持 ASCII STL 和 binary STL 解析为三角面数组。
2. 后端新增 STL 上传接口:
- `POST /api/model/upload`
- 使用请求体保存 STL 文件。
- 返回 `modelId``name``triangleCount`
3. 后端新增 DICOM 几何元数据提取:
- 基于排序后的 DICOM 文件读取 `ImagePositionPatient``ImageOrientationPatient``PixelSpacing`
- 构造 patient 坐标到体素坐标的转换。
- 元数据不足时降级为 STL 已是体素坐标。
4. 后端增强 `/api/library/reformat-preview`
- 支持 `modelId` 参数。
- 当传入模型时,根据 `plane``index` 计算 STL 三角面与当前 DICOM 切片平面的交线。
- 将交线栅格化并填充形成 mask叠加到 DICOM PNG 上。
- 返回 `maskPixels`,便于前端知道该帧是否有模型穿透。
5. 前端 DICOM 阅览新增模型切分控制:
- STL 文件上传按钮。
- 模型切分开关。
- 一个双端点进度条控制起点/终点,两个端点允许交叉。
- 起点/终点数值按当前切片总数约束。
6. 前端模型切分展示:
- 模型切分关闭:保留当前单帧 DICOM 阅览。
- 模型切分开启:显示起点帧、终点帧两张 DICOM 图,并请求后端叠加真实 STL mask。
- 不再显示无意义的 CT MASK 图片或伪造圆圈 mask。
7. 执行测试方案。
8. 更新 `工程分析/经验记录.md`
9. 提交并推送 Giteacommit 信息使用 `2026-05-08-02-36-12 实现STL模型切分mask`
10. 重新部署到 `http://192.168.3.11:3005/`
## 回滚思路
若 STL mask 功能不符合预期,可回滚 `web_backend.py` 中 STL 上传/解析/mask 叠加逻辑,以及 `WebSite/src/App.tsx` 中模型切分 UI恢复纯 DICOM 阅览。
## 风险控制
- STL 解析结果和 DICOM 体数据都使用缓存,避免高频重复解析。
- mask 叠加只影响阅览 PNG不修改原始 DICOM 和形变输出。
- 双端点进度条不影响普通 DICOM 阅览切片滑杆。
- 若 STL 与 DICOM 空间不匹配,前端仍显示 DICOM 切片,并以 `maskPixels=0` 表示该帧无交集。
## 人工审核状态
用户已明确本次不需要人工二次确认,直接执行。

View File

@@ -0,0 +1,94 @@
# 测试方案
开始时间2026-05-08-02-36-12
## 本次方案路径
`工程分析/测试方案-2026-05-08-02-36-12.md`
## 测试范围
- STL 上传接口。
- ASCII STL 和 binary STL 解析。
- STL 与 DICOM 切片相交 mask 生成。
- 模型切分开启后起点帧/终点帧双图显示。
- 双端点进度条起点/终点可交叉。
- 普通 DICOM 阅览不受影响。
- 前端类型检查、构建和 Python 语法检查。
- 重新部署后访问验证。
## 测试命令
Python 语法检查:
```bash
python -m py_compile web_backend.py head_extension_app.py
```
前端类型检查:
```bash
cd WebSite
npm run lint
```
前端构建:
```bash
cd WebSite
npm run build
```
后端函数级测试建议:
```bash
python - <<'PY'
from web_backend import parse_stl_bytes
sample = b'''solid demo
facet normal 0 0 1
outer loop
vertex 0 0 0
vertex 10 0 0
vertex 0 10 0
endloop
endfacet
endsolid demo
'''
triangles = parse_stl_bytes(sample)
print(triangles.shape)
PY
```
部署验证:
```bash
curl -I --max-time 5 http://192.168.3.11:3005/
curl -s --max-time 10 "http://127.0.0.1:8787/api/library/reformat-preview?id=demo_ori_head_ct&plane=coronal&index=256&window=bone"
```
## 手工验证点
- 打开 DICOM 阅览,普通冠状位/矢状位切片仍可查看。
- 上传 STL 后启用模型切分。
- 使用一个双端点进度条调节起点/终点帧。
- 将起点拖过终点或终点拖过起点后,界面仍能按两个端点显示切分结果。
- 起点帧和终点帧上显示真实 STL 切面 mask无交集时不显示假 mask。
- 不再出现单独无意义的 CT MASK 图片。
## 验收标准
- STL 上传返回模型信息。
-`modelId``/api/library/reformat-preview` 可返回叠加 mask 的 PNG。
- `python -m py_compile web_backend.py head_extension_app.py` 通过。
- `npm run lint` 通过。
- `npm run build` 通过。
- Gitea commit/push 完成。
- 重新部署后 `http://192.168.3.11:3005/` 返回 `200 OK`
## 残余风险
- mask 是否精确覆盖目标结构取决于 STL 与 DICOM 是否同坐标系、同单位、同方向。如果 STL 未与 DICOM patient 坐标配准,需要额外提供配准矩阵或模型平移/缩放/旋转控制。
## 人工审核状态
用户已明确本次不需要人工二次确认,直接执行。

View File

@@ -73,3 +73,21 @@ C. 解决问题方案
D. 后续如何避免问题
涉及整套 DICOM 体数据读取的接口必须考虑缓存、并发和请求节流,不能把滑杆这类高频 UI 操作直接绑定到重型后端计算。自动下载类逻辑必须记录已处理 job避免同一个完成状态在后续渲染或轮询中重复触发。
## 2026-05-08-02-36-12 实现 STL 模型切分 mask
A. 具体问题
用户要求模型切分不能再用象征性画圈或无意义 CT MASK 图,而要根据 STL 模型真实穿透 DICOM 的位置生成 mask并在 DICOM 起点帧、终点帧上显示。
B. 产生问题原因
当前仓库主线没有 STL 模型切分实现,只有 DICOM 冠状/矢状阅览。若用前端绘制圆圈或固定区域替代,会与 STL 几何和 DICOM 切片没有真实关系,无法表达语义分割切片形态。
C. 解决问题方案
后端新增 STL 上传、ASCII/Binary STL 解析、DICOM patient 坐标到体素坐标转换、STL 三角面与冠状/矢状切片平面求交、交线栅格化和填充形成 mask并叠加到 DICOM 阅览 PNG。前端新增模型切分开关、STL 上传、单条双端点进度条,以及起点帧/终点帧双图 mask 展示。
D. 后续如何避免问题
涉及医学影像与模型叠加时mask 必须来自真实几何或分割数据,不能用装饰性形状替代。若 STL 与 DICOM 坐标系不一致,应优先补充配准矩阵或平移/旋转/缩放参数,而不是在图像上手工假标。

View File

@@ -0,0 +1,53 @@
# 需求分析
开始时间2026-05-08-02-36-12
## 原始需求
用户要求严格使用代码编纂工作流,并在最开始确认整体流程。本次需求分析、实现方案、测试方案和执行修改都不需要人工二次确认。
本次具体需求:
1. 起点、终点合并到一个进度条里,进度条有两个端点,起点和终点可以调整顺序。
2. 模型切分启用后,不能只是象征性画圈,而要真正判断 STL 模型穿透 DICOM 的位置,并用颜色标出形成 mask。
3. 模型切分下方的帧进度栏没有实际意义。模型切分开启后,不需要在最后一张显示 CT也不需要当前无意义的 CT MASK 图片;应像之前一样用 DICOM 起点帧、终点帧对模型切两刀,并在这两个特定帧上显示 mask。这个 mask 代表重建 STL 模型原始语义分割的大致切片形态。
## 目标
- 在 DICOM 阅览中新增真实 STL 模型切分能力。
- 上传 STL 后,后端解析 STL 三角面片,按当前 DICOM 平面和起点/终点帧计算切片相交区域。
- 模型切分开启时,前端显示起点帧和终点帧两张 DICOM 切片,并叠加真实 STL 切面 mask。
- 用一个双端点进度条控制起点和终点,允许两个端点交叉,交叉后按数值顺序用于切分。
- 删除/不再显示无意义的 CT MASK 图片或伪 mask。
## 影响范围
- `web_backend.py`
- STL 上传接口。
- STL 解析、缓存。
- DICOM 阅览切片接口叠加真实 STL 切面 mask。
- `WebSite/src/App.tsx`
- DICOM 阅览弹层新增 STL 上传、模型切分开关、双端点进度条和双帧 mask 展示。
- 移除模型切分状态下无意义的单帧 CT/MASK 展示。
- `工程分析/经验记录.md`
## 当前定位
当前仓库主线中没有已有 `STL/模型切分/MASK` 代码,只有 DICOM 阅览和冠状/矢状重建预览。因此本次不是修补已有“画圈”代码,而是在现有 DICOM 阅览里补上真实 STL 切片 mask 能力。
## 约束
- 不引入大型前端 3D 库。
- 不改变真实 DICOM 形变算法。
- 不提交 STL、DICOM、mask 缓存图片、ZIP 或构建产物。
- STL 与 DICOM 的空间配准优先按 DICOM `ImagePositionPatient``ImageOrientationPatient``PixelSpacing` 转换;若元数据不足,则降级假设 STL 坐标已在体素坐标系中。
## 风险点
- STL 与 DICOM 是否同一坐标系直接决定 mask 是否对齐;若输入 STL 未配准到 DICOM patient 坐标mask 位置仍会偏。
- 不同 STL 拓扑可能导致切面轮廓不闭合mask 填充可能只显示轮廓或局部区域。
- 大 STL 模型解析和多切片 mask 计算可能耗时,需要缓存解析后的三角面。
## 待确认事项
用户已明确本次不需要二次人工确认,因此文档写完后直接执行。