第 6 阶段练习与参考答案
按教程目录完成第 19–21 章后,运行阶段示例。先尝试用观察结果回答,再查看参考答案。
练习 1:连接真正的体渲染管线
设 imageData 已有一个单分量 Point Data 标量,renderer 与 renderWindow 已创建。写出让它作为体对象出现所需的 Mapper、Volume 和 Renderer 连接。颜色与不透明度函数应配置在哪里?
参考答案
const mapper = vtkVolumeMapper.newInstance();
mapper.setInputData(imageData);
const volume = vtkVolume.newInstance();
volume.setMapper(mapper);
volume.getProperty().setRGBTransferFunction(0, colorFunction);
volume.getProperty().setScalarOpacity(0, opacityFunction);
renderer.addVolume(volume);
renderer.resetCamera();
renderWindow.render();
颜色和不透明度函数在 vtkVolumeProperty 上,不是直接设置在 vtkVolumeMapper 上。真实程序还要导入相应模块与 Volume 渲染 Profile。
练习 2:两个不同方向的采样间距
说明 setSampleDistance(0.5) 与 setImageSampleDistance(0.5) 分别改变什么。若想更密地检查沿视线的小结构,应先关注哪一个?若发现体的深处像被截断,还应检查什么上限?
参考答案
sampleDistance 改变同一条三维视线上相邻取样的距离;imageSampleDistance 改变屏幕平面上的射线密度。沿视线的小结构应先关注前者。若步长很小但体很厚,还要检查 maximumSamplesPerRay,并检查相机裁剪、透明度和数据范围,不能只凭一处参数判断。
练习 3:参考距离与透明度
不透明度函数给出 α=0.36,setScalarOpacityUnitDistance(0,1)。若实际采样距离为 0.5,概念上每段 α 约应是多少?把 sampleDistance 从 1 改为 0.5 后,画面是否一定逐像素完全不变?
参考答案
每半单位距离约为 1−(1−0.36)^0.5=0.2。两个同值半段合成后仍是 0.36。但新的采样位置可能读到不同插值标量,边界和小结构会变化,优化与光照也会影响结果,所以画面不保证逐像素相同。
练习 4:MIP 会留下什么
某条视线从近到远依次取到 [20,160,80,140]。MIP 的核心结果是什么?它能否告诉你 160 位于第二个采样位置?如果前面再加一个标量 170,结果如何变化?
参考答案
MIP 取最大标量 160,再将该值映射成屏幕颜色。仅靠投影像素无法知道它来自第二个位置。若前方再加入 170,最大值变为 170;原来的 160 不再决定该像素的最大强度显示。MIP 不做第 16 章那种前向后 α 累积。
练习 5:等值面阈值与不透明度倍率
在示例中把等值面阈值从 140 降到 100,可能出现什么变化?这与把合成体渲染的不透明度倍率从 1 调到 2 有何区别?
参考答案
降低等值面阈值会让更多满足阈值交叉的网格单元产生三角形;本示例中低值壳的一部分也可能进入结果,输出 vtkPolyData 的单元数会变化。不透明度倍率改变 VolumeProperty 的显示曲线,不会把图像转换成新三角网格;它可能让前方壳层更遮挡内部。
练习 6:切片位置与世界坐标
示例图像 originZ=-20、spacingZ=1、方向为单位矩阵。K=20 与 K=30 两张切片的世界 z 坐标各是多少?切换层号会改写体数据吗?
参考答案
K=20 对应 -20+20×1=0,K=30 对应 -20+30×1=10。imageMapper.setSlice(...) 只改变当前显示的截面,不改写 vtkImageData 或其标量数组。
练习 7:选择方法
请分别为以下目标选择一种优先显示方式,并说出一个局限:① 查看确定 z 层的原始强度分布;② 寻找投影方向的高强度区域;③ 得到可测量、可导出的边界三角网格;④ 观察透明外壳下的内部高值结构。
参考答案
① 切片;局限是一次只看一层。② MIP;局限是深度位置模糊。③ 等值面;局限是结果依赖阈值且只表示该边界。④ 合成体渲染;局限是外观强烈依赖颜色和不透明度函数,应结合切片验证。