vtk.js 实战之DICOM序列图读取(基于vtk.js和itk.js)

2,027 阅读1分钟

VTK.js 由于不能直接读取DICOM格式的文件,需要用到Itk.js。

安装itk.js

npm install itk

基于vite-vue 来配置相应的打包环境和config配置文件,具体如下:

文件vite.config.ts

import { fileURLToPath, URL } from "node:url";

import { defineConfig } from "vite";
import path from "path";

const itkConfig = path.resolve(__dirname, "src", "itkConfig.js");
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import copy from "rollup-plugin-copy";
const base = "/";
// https://vitejs.dev/config/
export default defineConfig({
  base: base,
  plugins: [
    vue(),
    vueJsx(),
    copy({
      targets: [
        { src: "node_modules/itk-wasm/dist/web-workers", dest: "dist/itk" },
        {
          src: "node_modules/itk-image-io",
          dest: "dist/itk",
          rename: "image-io",
        },
        {
          src: "node_modules/itk-mesh-io",
          dest: "dist/itk",
          rename: "mesh-io",
        },
      ],
      hook: "writeBundle",
    }),
  ],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
      "../itkConfig.js": itkConfig,
      "../../itkConfig.js": itkConfig,
    },
  },
});

src 根目录下面建立文件itkConfig.js

const itkConfig = {
  pipelineWorkerUrl: "/itk/web-workers/min-bundles/pipeline.worker.js",
  imageIOUrl: "/itk/image-io",
  meshIOUrl: "/itk/mesh-io",
  pipelinesUrl: "/itk/pipelines",
};

export default itkConfig;

具体可参考官方文档:

Using itk-wasm in a web browser application via Vite​wasm.itk.org/examples/vite.html

基于VTK的继承写法来仿照itkDICOMReader 的仿照写法 如下所示:

需要一个newInstance 和extend 的继承如下所示:

export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, DEFAULT_VALUES, initialValues);
  macro.obj(publicAPI, model);
  macro.algo(publicAPI, model, 0, 1);
  macro.setGet(publicAPI, model, ["fileName", "arrayName"]);
  vtkITKDicomImageReader(publicAPI, model);
}

export const newInstance = macro.newInstance(extend, "vtkITKDicomImageReader");
export default { newInstance, extend };

以上为基于VTK的继承写法 在此里面加上itk的api,利用itk-wasm 里面的readImageDICOMFileSeries 来读取序列图 。

获取后的image 是itk的数据 所以还需要vtk来做一次转换,基于vtkITKHelper中的convertItkToVtkImage 即可

import macro from "@kitware/vtk.js/macros";
import { readImageDICOMFileSeries } from "itk-wasm";
import vtkITKHelper from "@kitware/vtk.js/Common/DataModel/ITKHelper";

function vtkITKDicomImageReader(publicAPI, model) {
  // Set our className
  model.classHierarchy.push("vtkITKDicomImageReader");

  // Returns a promise to signal when image is ready
  publicAPI.readFileSeries = (files, fileName) => {
    if (!files || !files.length || files === model.files) {
      return Promise.resolve();
    }

    if (fileName && fileName !== model.fileName) {
      model.fileName = fileName;
    }

    model.files = files;

    return readImageDICOMFileSeries(files).then(({ webWorker, image }) => {
      const imageData = vtkITKHelper.convertItkToVtkImage(image, {
        scalarArrayName: model.arrayName || getArrayName(model.fileName),
      });
      model.output[0] = imageData;

      publicAPI.modified();

      return imageData;
    });
  };

  publicAPI.requestData = (/* inData, outData */) => {
    publicAPI.readFileSeries(model.files, model.fileName);
  };
}

以上是封装了一个DICOMReader读取数据器的实现思路。 下一篇文章将会基于这个读取器来实现数据的渲染 3D模型。