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

如何用Three.js DataArrayTexture渲染DICOM或单位置NRRD图像?

实现Three.js Texture2DArray风格的DICOM/NRRD体数据渲染

方案2:基于NRRDLoader的直接实现(推荐)

Three.js的NrrdLoader加载3D体数据后,可直接提取原始像素数组和维度信息,用来创建DataArrayTexture,完全匹配你想要的texture2darray示例效果:

  1. 加载NRRD并提取体数据
    使用NrrdLoader加载后,回调返回的volume对象包含体数据的核心信息:

    import * as THREE from 'three';
    import { NrrdLoader } from 'three/addons/loaders/NrrdLoader.js';
    
    const loader = new NrrdLoader();
    loader.load('your-volume.nrrd', (volume) => {
      // 提取体数据的尺寸和原始像素数组
      const { width, height, depth, data } = volume;
      
      // 创建DataArrayTexture
      const textureArray = new THREE.DataArrayTexture(
        data,    // 合并后的体数据数组
        width,   // 单切片宽度
        height,  // 单切片高度
        depth    // Z轴切片数量
      );
    
      // 配置纹理参数,匹配数据格式
      textureArray.format = THREE.RedFormat; // 单通道体数据用RedFormat,多通道按需调整
      textureArray.type = THREE.UnsignedByteType; // 匹配NRRD的数据类型(如Uint16则用UnsignedShortType)
      textureArray.minFilter = THREE.LinearFilter;
      textureArray.magFilter = THREE.LinearFilter;
      textureArray.wrapR = THREE.ClampToEdgeWrapping; // Z轴边界不重复
      textureArray.needsUpdate = true;
    
      // 后续即可像texture2darray示例一样使用该纹理
      // 比如创建平面材质,在Shader中采样指定Z切片
    });
    
  2. Shader中采样Texture2DArray
    参考示例的Shader逻辑,传入切片索引即可渲染对应Z层:

    uniform sampler2DArray uTextureArray;
    uniform float uSliceIndex;
    uniform vec2 uResolution;
    
    void main() {
      vec2 uv = gl_FragCoord.xy / uResolution;
      gl_FragColor = texture(uTextureArray, vec3(uv, uSliceIndex));
    }
    

方案1:前端直接合并DICOM切片(无需预生成数组文件)

如果你不想转NRRD,可以直接在前端解析DICOM切片并合并,跳过OpenGL处理步骤:

  1. 解析DICOM切片
    使用dicom-parser库解析每个DICOM文件,提取像素数据和Z轴位置信息:

    import dicomParser from 'dicom-parser';
    
    // 假设已获取所有DICOM文件的File对象数组
    const dicomFiles = [...];
    const slices = [];
    
    for (const file of dicomFiles) {
      const arrayBuffer = await file.arrayBuffer();
      const dataSet = dicomParser.parseDicom(arrayBuffer);
      
      // 提取像素数据(注意DICOM可能有压缩格式,需额外处理)
      const pixelData = dataSet.byteArray.slice(
        dataSet.elements.x7fe00010.dataOffset,
        dataSet.elements.x7fe00010.dataOffset + dataSet.elements.x7fe00010.length
      );
      // 提取Z轴位置(用InstanceNumber或ImagePositionPatient的Z值排序)
      const zPosition = dataSet.elements.x00200013 ? dataSet.elements.x00200013.value[0] : 0;
      
      slices.push({ pixelData, width: dataSet.elements.x00280010.value[0], height: dataSet.elements.x00280011.value[0], zPosition });
    }
    
  2. 排序并合并切片
    按Z轴位置排序后,将所有切片的像素数组合并为一个大数组:

    // 按Z轴位置排序切片
    slices.sort((a, b) => a.zPosition - b.zPosition);
    const width = slices[0].width;
    const height = slices[0].height;
    const depth = slices.length;
    
    // 创建合并后的体数据数组
    const mergedData = new Uint8Array(width * height * depth);
    slices.forEach((slice, index) => {
      mergedData.set(slice.pixelData, index * width * height);
    });
    
    // 用合并后的数组创建DataArrayTexture,步骤同方案2
    const textureArray = new THREE.DataArrayTexture(mergedData, width, height, depth);
    // ... 配置纹理参数 ...
    

注意事项

  • 确保DICOM/NRRD的所有切片尺寸一致,否则无法创建DataArrayTexture
  • DICOM像素数据可能存在位深、压缩、窗宽窗位等问题,需根据实际情况做预处理
  • WebGL 2.0支持Texture2DArray,确保你的环境启用了WebGL 2.0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:30:56