技术标签: 医学影像 CornerStone3D 前端 cornerstone3D
Cornerstone3D是一个专门为处理三维医学影像而设计的JavaScript库。
它是Cornerstone项目的一部分,旨在为医学影像社区提供高性能、可扩展且易于使用的开源Web工具,专注于提供交互式的3D医学图像浏览体验,适用于多种医学影像格式。
健壮的DICOM解析:能够处理和显示各种3D医学影像格式,如CT、MRI和PET扫描等,支持Dicom格式、NifTi格式的影像加载
高性能渲染:使用WebGL进行图像渲染、使用多线程进行图像编码,优化了图像的加载和显示速度,从而提供了流畅的用户体验
模块化设计:设计了灵活的架构,允许开发者扩展自己的工具和定制功能,以适应特定的医学影像应用需求。
Cornerstone3D 和 Cornerstone 版本对比,主要在图像处理、渲染性能上进行了提升。2D版本无法更好的支持复杂场景的使用,例如多平面重建、Series融合等等。以下是从不同场景进行的对比:
图像处理: 专注于处理和展示二维医学影像数据
渲染性能:针对2D图像优化,提供高效的加载和显示性能。
工具和功能:包括基本的图像操作工具,如缩放、平移、旋转、亮度/对比度调节,以及医学影像中常用的注释和测量工具。
图像处理:能够处理和展示三维医学影像数据,如从CT或MRI扫描得到的体积数据集。
渲染性能:使用WebGL等技术进行3D渲染,优化了处理和显示大型体积数据集的能力。
工具和功能:除了包含2D版本的基本功能外,还提供3D特有的功能,如多平面重建(MPR)、体积渲染、图像分割等等。
vtk.js是一个开源的javascript库,用于3D计算机图形,图像处理和可视化。Cornerstone3D的渲染引擎被设计为使用vtk.js进行3D渲染
Cornerstone3D使用HTML5 canvas元素和WebGL 2.0 GPU渲染来渲染所有现代浏览器都支持的图像。但是并不是所有浏览器都支持volume streaming(使用SharedArrayBuffer创建共享内存)等高级功能。
Chrome > 68
Firefox > 79
Edge > 79
需要重点关注 SharedArrayBuffer 问题,如果项目是部署在非安全上下文的环境中,SharedArrayBuffer 默认是不支持的,需要设置跨域隔离。
原文:https://www.cornerstonejs.org/docs/getting-started/scope
Cornerstone3D是一个Javascript库,它利用纯粹的网络标准实现医学图像的3D渲染。该库在可能的情况下采用WebGL进行GPU加速渲染。Cornerstone3DTools是Cornerstone3D的同级库,包含了多种操控和注释工具,用于与图像进行交互。
Cornerstone3D的范围 并不包括 处理图像/体积的加载和元数据解析,只作用于图像渲染和缓存。应该使用imageLoader.registerImageLoader和volumeLoader.registerVolumeLoader注册到Cornerstone3D来使用图像/体积的请求加载。
在Cornerstone3D中,发布了第一个volumeLoader,streaming-image-volume-loader,它能够逐个流式传输体积图像。
Cornerstone3D中的ImageId是一个用于识别单个图像以供Cornerstone显示的URL。该URL被Cornerstone用来确定调用哪个图像加载器插件来实际加载图像。
值得注意的是,Cornerstone3D将图像的加载工作委托给已注册的图像加载器。
这种策略允许Cornerstone同时显示从不同服务器通过不同协议获取的多个图像。
ImageLoader是一个JavaScript函数,负责接收ImageId并返回一个图像对象。由于加载图像通常需要调用服务器,因此图像加载的API需要是异步的。Cornerstone要求Image Loaders返回一个包含Promise的对象,Cornerstone将使用这个Promise异步接收图像对象,或者在发生错误时接收一个错误信息
Cornerstone WADO Image Loader:支持DICOM第10部分图像;支持WADO-URI和WADO-RS;支持多帧DICOM实例;支持从文件对象读取DICOM文件
Cornerstone Web Image Loader: 支持 PNG and JPEG 文件
Cornerstone-nifti-image-loader:支持 NifTi格式文件
使用registerImageLoader注册指定协议的加载器,以下示例表示:wadouri 协议的图像使用 cornerstoneDICOMImageLoader加载器加载
cornerstone.imageLoader.registerImageLoader('wadouri', cornerstoneDICOMImageLoader.wadouri.loadImage);
cornerstoneDICOMImageLoader.wadouri.register(cornerstone);
cornerstoneDICOMImageLoader.external.cornerstone = cornerstone;
cornerstoneDICOMImageLoader.external.dicomParser = dicomParser;
为Cornerstone3D库提供了一个DICOM图像加载器。这是[cornerstoneDICOMImageLoader]的后继产品,支持在3D库中使用。主要提供了以下新增特性:
Typescript支持(及类型定义)
更佳的开发体验(例如,单一仓库、代码规范检查等)
主要特点为:
实现了一个通过HTTP GET请求加载DICOM实例的Cornerstone图像加载器。
可与WADO-URI服务器一起使用
可与Orthanc的文件终端一起使用
可与任何通过HTTP GET返回DICOM P10实例的服务器一起使用
实现了一个用于WADO-RS(DICOMWeb)的Cornerstone图像加载器
支持许多流行的传输语法和光度解释
动态地利用WebAssembly(WASM)构建每个编解码器,显著提高图像解码性能,并使我们能够在需要时动态加载编解码器,从而减少构建时间和复杂性
用于在Web Workers中执行CPU密集型任务的框架
用于图像解码
用于CPU密集型任务(例如,图像处理)
ImageLoader使用registerImageLoader API在Cornerstone中注册,以加载特定的ImageId URL方案
应用程序使用loadImage API来加载堆栈中的图像,或者使用createAndCacheVolume API来加载体积数据。
Cornerstone将加载图像的请求委托给已注册相应ImageId URL方案的ImageLoader。
ImageLoader将返回一个包含Promise的图像加载对象,
一旦获取到像素数据,它将用相应的图像对象解析这个Promise。获取像素数据可能需要通过XMLHttpRequest调用远程服务器,对像素数据进行解压(例如,来自JPEG 2000的数据),并将像素数据转换成Cornerstone能够理解的格式(例如,RGB与YBR颜色)。通过解析Promise返回的图像对象,随后将通过renderingEngine API显示。
Volume是一个具有空间物理大小和方向的3D数据阵列。
它可以通过组合3D成像系列的像素数据和元数据来构建,或者可以由应用程序从头定义。一个Volume拥有FrameOfReferenceUID、体素间距(x, y, z)、体素尺寸(x, y, z)、原点和方向向量,这些特征唯一地定义了它相对于患者坐标系统的坐标系统
在Cornerstone3D中,使用ImageVolume基类来表示3D图像体积。所有的Volume都是从这个类派生的。例如StreamingImageVolume,它被用来表示一个图像被流式传输的Volume。
所以所有的Volume都实现了以下这个接口:
interface IImageVolume {
/** 【缓存中Volume的唯一标识符】unique identifier of the volume in the cache */
readonly volumeId: string
/** volume dimensions */
dimensions: Point3
/** volume direction */
direction: Float32Array
/** volume metadata */
metadata: Metadata
/** volume origin - set to the imagePositionPatient of the last image in the volume */
origin: Point3
/** volume scalar data */
scalarData: any
/** volume scaling metadata */
scaling?: {
PET?: {
SUVlbmFactor?: number
SUVbsaFactor?: number
suvbwToSuvlbm?: number
suvbwToSuvbsa?: number
}
}
/** volume size in bytes */
sizeInBytes?: number
/** volume spacing */
spacing: Point3
/** number of voxels in the volume */
numVoxels: number
/** volume image data as vtkImageData */
imageData?: vtkImageData
/** openGL texture for the volume */
vtkOpenGLTexture: any
/** loading status object for the volume containing loaded/loading statuses */
loadStatus?: Record<string, any>
/** imageIds of the volume (if it is built of separate imageIds) */
imageIds?: Array<string>
/** volume referencedVolumeId (if it is derived from another volume) */
referencedVolumeId?: string // if volume is derived from another volume
/** method to convert the volume data in the volume cache, to separate images in the image cache */
convertToCornerstoneImage?: (
imageId: string,
imageIdIndex: number
) => IImageLoadObject
}
与ImageLoader类似,VolumeLoader接收一个Volume ID和加载Volume所需的其他信息,并返回一个解析为体积的Promise。
这个Volume可以由一组2D图像(例如,imageIds)构建,也可以由一个3D数组对象(如NIFTI格式)构建。我们添加了cornerstoneStreamingImageVolumeLoader库来支持将2D图像(imageIds)流式传输成3D体积。
使用registerVolumeLoader来定义一个Volume Loader
import {
cornerstoneStreamingImageVolumeLoader,
cornerstoneStreamingDynamicImageVolumeLoader,
} from '@cornerstonejs/streaming-image-volume-loader';
// 注册体积加载器 => 当 CornerstoneJS 需要加载一个类型为 'cornerstoneStreamingImageVolume' 的体积数据时,它将会使用这个加载器。
volumeLoader.registerVolumeLoader(
'cornerstoneStreamingImageVolume',
cornerstoneStreamingImageVolumeLoader,
);
由于在StreamingImageVolume中3D Volume是由2D图像组成的,它的体积元数据来源于2D图像的元数据,所以这个loader需要在初始时调用来获取图像元数据。这样做不仅可以在内存中预分配和缓存Volume,还可以在加载2D图像时渲染Volume(渐进式加载)
通过预先从所有图像(imageId)中获取元数据,不需要为每个imageId创建Image对象,将图像的pixelData直接插入到正确位置的volume中即可,这样保证了速度和内存效率。
StreamingImageVolume基于一系列获取的图像(2D)加载Volume,Volume可以实现将其3D像素数据转换为2D图像的功能,而无需通过网络重新请求它们。
同样的,如果一组imageid具有Volume的属性(相同的FromOfReference, origin, dimension, direction和pixelSpacing),那么Cornerstone3D可以从一组imageid创建一个Volume。
const imageIds = ['wadors:imageId1', 'wadors:imageId2'];
const ctVolumeId = 'cornerstoneStreamingImageVolume:CT_VOLUME';
const ctVolume = await volumeLoader.createAndCacheVolume(ctVolumeId, {
imageIds: ctImageIds,
});
await ctVolume.load();
由于Volume的创建和缓存(createAndCacheVolume)与图像数据(load)的加载是分离的。所以支持以任何顺序加载图像,以及重新排序图像请求以正确顺序加载图像的能力。
根据一组imageIds,计算Volume的元数据,如间距、原点、方向等。
实例化一个新的StreamingImageVolume
StreamingImageVolume实现了加载方法(.load)
通过使用imageLoadPoolManager来实现加载请求
每个加载的帧(imageId)被放置在3D体积中的正确切片位置
返回一个体积加载对象,该对象包含一个解析为体积的promise。
RenderingEngine允许用户创建Viewports,将这些viewport与屏幕上的 HTML 元素关联,并使用WebGL 画布将数据渲染到这些元素上。
值得注意的是,RenderingEngine 能够渲染多个viewport,而无需创建多个引擎。
在Cornerstone3D 中,从零开始构建了 RenderingEngine,并使用 vtk.js 作为渲染的支撑,vtk.js 是一个 3D 渲染库,能够利用 WebGL 进行 GPU 加速渲染。
在 Cornerstone(2D)中,每个viewport都使用 WebGL 画布处理数据。随着viewport数量的增加,尤其在复杂的影像应用场景中(例如,同步视窗),因为会导致屏幕上画布的大量更新,以及随着视窗数量增加而性能下降。
在 Cornerstone3D 中,在屏幕外处理数据。这意味着我们有一个大型的不可见画布(离屏),它内部包含了所有屏幕上的画布。当用户操纵数据时,离屏画布中相应的像素会被更新,在渲染时,将数据从离屏画布复制到每个视窗的屏幕上画布。由于复制过程比重新渲染每个视窗上的操纵更快,因此解决了性能下降的问题。
vtk.js 提供了用于渲染的标准渲染功能。此外,在 Cornerstone3D 中,引入了共享体积映射器(Shared Volume Mappers),以便在任何可能需要的视窗中重用数据,而无需复制数据。
import {
RenderingEngine } from '@cornerstonejs/core';
const renderingEngineId = 'myEngine';
const renderingEngine = new RenderingEngine(renderingEngineId);
const viewportInput = [
// CT Volume Viewport - Axial
{
viewportId: 'ctAxial',
type: ViewportType.ORTHOGRAPHIC,
element: htmlElement1,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL,
},
},
// CT Volume Viewport - Sagittal
{
viewportId: 'ctSagittal',
type: ViewportType.ORTHOGRAPHIC,
element: htmlElement2,
defaultOptions: {
orientation: Enums.OrientationAxis.SAGITTAL,
},
},
// CT Axial Stack Viewport
{
viewportId: 'ctStack',
type: ViewportType.STACK,
element: htmlElement3,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL,
},
},
];
renderingEngine.setViewports(viewportInput);
renderingEngine.renderViewports(['ctAxial','ctSagittal','ctStack']);
在 Cornerstone3D 中,viewport是由 HTML 元素创建的,我们需要提供用于创建viewport的元素。然后进行初始化绑定
viewport主要分为 2D栈视图、Volume体视图、3D视图,根据不同的渲染需求进行选择。无论是哪一种视图类型,都是通过 RenderingEngine API 进行创建
适用于呈现一堆图像,这些图像可能属于也可能不属于同一图像。
Stack可以包含各种形状、大小和方向的2D图像
const viewport = renderingEngine.getViewport('stackId');
await viewport.setStack(imageIds);
适合于渲染被认为是一个3D图像的体积数据。
使用VolumeViewport可以通过设计实现多平面重组或重建(MPR),可以从不同的方向进行体积可视化,而不会增加性能成本。
用于两个series之间的图像融合
适用于实际的三维立体数据渲染。
有不同类型的预设,如骨,软组织,肺等。
所有的Viewport都继承自Viewport类,它提供了一个displayArea字段。该字段可用于以编程方式设置图像的初始缩放/平移。
默认情况下,视口将使dicom图像适合屏幕。displayArea字段支持以下配置内容:
type DisplayArea = {
imageArea: [number, number], // areaX, areaY
imageCanvasPoint: {
imagePoint: [number, number], // imageX, imageY
canvasPoint: [number, number], // canvasX, canvasY
},
storeAsInitialCamera: boolean,
};
在初始化时,如果想要设置图像为200%,则设置如下
imageArea: [0.5, 0.5],
在初始化时,如果想要左对齐图像,则设置如下
imageCanvasPoint: {
imagePoint: [0, 0.5],
canvasPoint: [0, 0.5],
};
这意味着画布上的左(0)中间(0.5)点需要与图像上的左(0)中间(0.5)点对齐。数值基于完整图像的%大小。
在创建视图时进行初始化
renderingEngine.setViewports([{
viewportId: 'ctAxial',
type: ViewportType.ORTHOGRAPHIC,
element: htmlElement1,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL,
displayArea:{
// 需要更改的配置项
}
},
}]);
医学影像通常附带大量非像素级的元数据,例如图像的像素间距、患者 ID 或扫描获取日期等等。对于某些文件类型(例如 DICOM),这些信息存储在文件头中,可以被读取、解析并在应用程序中传递。而对于其他类型(例如 JPEG、PNG),这些信息需要独立于实际像素数据提供。
元数据提供器是一个 JavaScript 函数,作为访问 Cornerstone 中与图像相关元数据的接口。用户也可以定义自己的提供器函数,以返回他们希望的每个特定图像的任何元数据。
提供器需要实现一个get函数,该函数接收一个 type 和 ImageId, 返回当前ImageId中业务需要的数据
function addInstance(imageId, scalingMetaData) {
const imageURI = csUtils.imageIdToURI(imageId);
scalingPerImageId[imageURI] = scalingMetaData;
}
function get(type, imageId) {
if (type === 'scalingModule') {
const imageURI = csUtils.imageIdToURI(imageId);
return scalingPerImageId[imageURI];
}
}
export default {
addInstance, get };
通过addProvider函数,在CornerStone中添加提供器
cornerstone.metaData.addProvider(
ptScalingMetaDataProvider.get.bind(ptScalingMetaDataProvider),
10000,
);
由于可以注册多个元数据提供器,因此在添加提供器时,可以为其定义一个优先级数字。
当需要请求元数据时,Cornerstone 将按照提供器的优先级顺序请求图像的元数据(如果提供器对于图像 ID 返回未定义,则 Cornerstone 将转向下一个提供器)。例如,如果 provider1 注册时优先级为 10,而 provider2 注册时优先级为 100,则首先向 provider2 请求图像 ID 的元数据。上面的示例中我们定义了一个优先级为10000的provider
文章浏览阅读3.8k次。1、将下载好的萤石js插件,添加到SoringBoot项目中。位置可参考下图所示。(容易出错的地方,在将js插件在html页面引入时,发生路径错误的问题)所以如果对页面中引入js的路径不清楚,可参考下图所示存放路径。2、将ezuikit.js引入到demo-live.html中。(可直接将如下代码复制到你创建的html页面中)<!DOCTYPE html><html lan..._ezuikit 测试的url
文章浏览阅读322次。第二步,在弹出的对话框选择,设备驱动—>PLC—>莫迪康—>ModbusRTU—>COM,根据配置软件选择的协议选期期,这里以此为例,然后点击“下一步”。第四步,把使用虚拟串口打勾(GPRS设备),根据需要选择要生成虚拟口,这里以选择KVCOM1为例,然后点击“下一步”设备ID即Modbus地址(1-255) 使用DTU时,为下485接口上的设备地址。第六步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“第五步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“_组态王ua
文章浏览阅读9.4k次,点赞22次,收藏19次。安装npm相当于安装node.js,Node.js已自带npm,安装Node.js时会一起安装,npm的作用就是对Node.js依赖的包进行管理,也可以理解为用来安装/卸载Node.js需要装的东西_npm安装配置
文章浏览阅读748次,点赞21次,收藏26次。大家好,小编来为大家解答以下问题,python基础训练100题,python入门100例题,现在让我们一起来看看吧!宝子们还在新手村练级的时候,不单要吸入基础知识,夯实自己的理论基础,还要去实际操作练练手啊!由于文章篇幅限制,不可能将100道题全部呈现在此除了这些,下面还有我整理好的基础入门学习资料,视频和讲解文案都很齐全,用来入门绝对靠谱,需要的自提。保证100%免费这不,贴心的我爆肝给大家整理了这份今天给大家分享100道Python练习题。大家一定要给我三连啊~
文章浏览阅读1k次。 为了在 Linux ( Ubuntu) 上安装sublime,一般大家都会选择常见的教程或是 sublime 官网教程,然而在国内这种方法可能失效。为此,需要用安装包安装。以下就是使用官网安装包安装的教程。打开 sublime 官网后,点击右上角 download, 或是直接访问点击打开链接,即可看到各个平台上的安装包。选择 Linux 64 位版并下载。下载后,打开终端,进入安装..._ubuntu 安装sumlime text打不开
文章浏览阅读563次,点赞13次,收藏6次。CrossOver24是一款类虚拟机软件,专为macOS和Linux用户设计。它的核心技术是Wine,这是一种在Linux和macOS等非Windows操作系统上运行Windows应用程序的开源软件。通过CrossOver24,用户可以在不购买Windows授权或使用传统虚拟机的情况下,直接在Mac或Linux系统上运行Windows软件和游戏。该软件还提供了丰富的功能,如自动配置、无缝集成和实时传输等,以实现高效的跨平台操作体验。
文章浏览阅读1.7k次。一个用聊天的方式让ChatGPT帮我写的线程安全的环形List_为什么gpt一写list就卡
文章浏览阅读336次。我们在前面的文章里曾写过Web应用中乱码产生的原因和处理方式,旧文回顾:深度揭秘乱码问题背后的原因及解决方式其中我们提到可以通过Filter的方式来设置请求和响应的encoding,来解..._filterconfig selectencoding
文章浏览阅读651次。转自:http://www.jb51.net/article/36480.htmencodeURI和decodeURI是成对来使用的,因为浏览器的地址栏有中文字符的话,可以会出现不可预期的错误,所以可以encodeURI把非英文字符转化为英文编码,decodeURI可以用来把字符还原回来_js encodeur decodeurl
文章浏览阅读1.9w次,点赞6次,收藏3次。前言在日常的Android开发当中,我们肯定要打包apk。但是今天我打包的时候遇到一个很奇怪的问题Android The destination folder does not exist or is not writeable,大意是目标文件夹不存在或不可写。出现问题的原因以及解决办法上面有说报错的中文大意是:目标文件夹不存在或不可写。其实问题就在我们的打包界面当中图中标红的Desti..._the destination folder does not exist or is not writeable
文章浏览阅读94次。一、配置代码编辑区的样式 <1>打开Eclipse,Help —> Install NewSoftware,界面如下: <2>点击add...,按下图所示操作: name:随意填写,Location:http://eclipse-color-th..._ecplise高大上设置
文章浏览阅读2.8k次。一,下载mysql:http://dev.mysql.com/downloads/mysql/; 打开页面之后,在Select Platform:下选择linux Generic,如果没有出现Linux的选项,请换一个浏览器试试。我用的谷歌版本不可以,换一个别的浏览器就行了,如果还是不行,需要换一个翻墙的浏览器。 二,下载完后解压缩并放到安装文件夹下: 1、MySQL-client-5.6.2_linux mysql 安装 mysql-5.6.24-1.linux_glibc2.5.x86_64.rpm-bundle