You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求XTK/AMI.js实现FreeSurfer脑表面叠加T1.mgz的方案

实现FreeSurfer表面与T1切片叠加效果的方案指引

首先明确:你的需求完全可以通过XTK实现,而且你的初步代码已经走在了正确的方向上,只需要调整几个关键细节就能匹配目标的freeview效果。下面我会给你具体的优化指引,同时也聊聊AMI.js的备选情况。

一、XTK优化实现步骤

1. 精准同步正交投影与切片视角

你的setMainSlice函数里手动计算正交矩阵的方式容易出错,XTK内置了可以直接复用的2D渲染器投影参数,能让3D视图的切面和2D切片完全对齐:

function setMainSlice() {
  // 根据当前交互的切片轴,获取对应2D渲染器的投影参数
  const activeRenderer = {
    X: view2D_X,
    Y: view2D_Y,
    Z: view2D_Z
  }[volume3D.sliceMode];
  
  // 切换3D相机到正交模式,并同步投影矩阵
  view3D.camera.mode = 'ORTHOGRAPHIC';
  view3D.camera.projection = activeRenderer.camera.projection;
  
  // 调整相机位置,确保切片中心完全重合
  const spacing = volume3D.spacing;
  const position = [
    volume3D.indexX * spacing[0],
    volume3D.indexY * spacing[1],
    volume3D.indexZ * spacing[2]
  ];
  view3D.camera.position = position;
  
  view3D.render();
}

2. 匹配freeview的表面轮廓样式

freeview里的表面是显示为清晰的轮廓线,而非填充面,所以需要调整mesh的渲染属性:

function loadMeshes() {
  for (var a = 0; a < 6; a++) {
    try {
      meshes[a] = new X.mesh();
      meshes[a].file = meshFiles[a];
      meshes[a].color = colors[a];
      meshes[a].visible = true;
      // 开启线框模式,关闭填充
      meshes[a].wireframe = true;
      // 设置合适的线宽(匹配freeview的视觉效果)
      meshes[a].lineWidth = 2;
      // 调整透明度,避免轮廓被切片遮挡
      meshes[a].opacity = 0.9;
      view3D.add(meshes[a]);
    } catch(err) {
      console.log('failed to load: '+meshFiles[a]);
      console.log(err.message);
    }
  }
}

3. 体积切片渲染设置

要让体积只显示当前选中的切片(而非整个体素),需要开启切片模式:

// 初始化volume时添加
volume3D = new X.volume();
volume3D.file = t1File;
// 默认使用Z轴切片模式,后续随交互切换
volume3D.sliceMode = X.sliceMode.Z;
// 设置默认中间切片(MGZ通常是256x256x256,所以选128)
volume3D.indexZ = 128;

4. 修复渲染器初始化与同步逻辑

调整初始化顺序,确保volume被正确添加到所有渲染器,同时优化切片滚动的同步逻辑:

addLoadEvent(function () {
  // 先初始化所有渲染器
  view3D = new X.renderer3D();
  view3D.container = 'view3D_div';
  view3D.init();

  view2D_X = new X.renderer2D();
  view2D_X.container = 'view2D_X_div';
  view2D_X.orientation = 'X';
  view2D_X.init();

  view2D_Y = new X.renderer2D();
  view2D_Y.container = 'view2D_Y_div';
  view2D_Y.orientation = 'Y';
  view2D_Y.init();

  view2D_Z = new X.renderer2D();
  view2D_Z.container = 'view2D_Z_div';
  view2D_Z.orientation = 'Z';
  view2D_Z.init();

  // 创建并配置volume
  volume3D = new X.volume();
  volume3D.file = t1File;
  volume3D.sliceMode = X.sliceMode.Z;
  volume3D.indexZ = 128;

  // 将volume添加到所有渲染器
  view3D.add(volume3D);
  view2D_X.add(volume3D);
  view2D_Y.add(volume3D);
  view2D_Z.add(volume3D);

  // 加载表面mesh
  loadMeshes();

  // 设置切片滚动的同步回调
  view2D_X.onScroll = function() {
    volume3D.sliceMode = X.sliceMode.X;
    setMainSlice();
  };
  view2D_Y.onScroll = function() {
    volume3D.sliceMode = X.sliceMode.Y;
    setMainSlice();
  };
  view2D_Z.onScroll = function() {
    volume3D.sliceMode = X.sliceMode.Z;
    setMainSlice();
  };

  // 初始渲染
  view3D.render();
  view2D_X.render();
  view2D_Y.render();
  view2D_Z.render();
});

二、关于AMI.js的备选方案

目前AMI.js的路线图虽然标注了FreeSurfer表面和MGZ格式支持,但这些功能尚未实现。如果要基于AMI.js完成需求,你需要自行编写MGZ格式解析器和FreeSurfer .orig/.pial/.white文件的加载逻辑,这会涉及不少底层的医学影像格式处理工作,开发成本较高。因此优先推荐使用XTK方案,能更快达到你的目标效果。

内容的提问来源于stack exchange,提问作者Ben Wagner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:20