004: VTK读入数据---vtkImageData详细说明
VTK医学图像处理---vtkImageData类
目录
VTK医学图像处理---vtkImageData类
简介:
1 Mricro软件的安装和使用
(1) Mricro安装
(2) Mricro转换DICOM为裸数据
2 从硬盘读取数据到vtkImageData
3 vtkImageData转RGB或RGBA格式
4 练习
总结
简介:
对于医学图像来说,vtkImageData是使用频率非常高的类,因为医学图像通常为较为规则的矩形或容积类型(三维),而vtkImageData类主要就是用于存储此类数据的,vtk中相关算法(比如阈值、缩放等)的输入和输出也是vtkImageData类,熟练掌握vtkImageData类非常重要。
vtkDICOMImageReader类读取文件夹中的DICOM文件后,DICOM数据也存储在vtkImageData类中,本篇博文将跳过vtkDICOMImageReader类,直接从硬盘读取数据到vtkImageData类中,以增强大家对vtkImageData类的熟悉。
由于DICOM格式非常负责,有专门的开源库对DICOM文件进行解析,比如DCMTK(DCMTK - dicom.offis.de),我们不打算详细介绍DICOM标准,因此我们将借助一个免费的软件Mricro(建议大家学会使用给软件,不管是开发还是做科研都非常有用)来将DICOM文件转换为原始数据,采用C语言从硬盘读取原始数据到vtkImageData类中。
本博文主要包括为 Mricro的安装和使用,从硬盘读取数据到vtkImageData类,vtkImageData类的详细介绍。
1 Mricro软件的安装和使用
下载地址:MRIcro software guide (sc.edu)
打开网页后,点击下图中红色方框中的链接开始下载。
(1) Mricro安装
下载后,解压会看到下面的图标,双击安装,提出是否安装,选择是,一路默认安装,详细步骤如下图:
(2) Mricro转换DICOM为裸数据
在开始栏中搜索Mricro,或从所有应用程序里面找到Mricro启动,启动后的界面为:
DICOM数据下载地址:【免费】VTK-医学图像处理博文中需要的DICOM测试数据资源-CSDN文库
下载DICOM数据解压,在Mricro软件的菜单项中选择 Import--Convert foreign to Analyze,跳出选择对话框。
在Number of Files中要输入待转换的DICOM文件张数, 例如这里我们转换10张,就在该输入框内填写10,记得勾选 Open sequential files:ignore filename选项,然后点击 Select。
在Conversion Options框中,继续点击 OK
这里有时候会跳出一个或两个提示框,不用管它,点击OK继续
到 Select 对话框后,随便选中一张待转换的DICOM文件,然后再文件名中输入要保存为裸数据的名称,点击 打开。
单击 打开后,会跳出导出保存框,在保存框中输入要保存的名称,点击 保存按钮进行保存。
打开DicomFiles所在文件夹,会发现里面多了两个文件:test.hdr和 test.img
其中 test.hdr文件中保存的数据的长宽高,空间位置等信息
test.img文件中就是纯粹的裸数据,接下来我们将读取test.img中的数据到vtkImageData中。
双击test.hdr,用Mricro软件打开它,在软件的左侧,可以看到test.img中的数据长为512,宽为512,一共有10张图像,数据类型为short。
2 从硬盘读取数据到vtkImageData
老规矩,先看下代码,也可以拷贝到自己的项目中,运行下:
#define _CRT_SECURE_NO_WARNINGS#include "vtkImageMapToWindowLevelColors.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkImageData.h"
#include "vtkNew.h"
#include "vtkDICOMImageReader.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkCamera.h"
int ImageSlice = 0;
void main()
{vtkNew<vtkImageData> imageData;imageData->SetDimensions(512, 512, 10);imageData->SetSpacing(.49, .49, .7);imageData->SetOrigin(0.0, 0.0, 0.0);imageData->AllocateScalars(VTK_SHORT, 1);void *ptr = imageData->GetScalarPointer();size_t bSize = 512 * 512 * 10;FILE* pFile = fopen("D:\\DicomFiles\\test.img","rb+");if (NULL == pFile)return;fread(ptr, sizeof(short), bSize, pFile);fclose(pFile);int* ext = imageData->GetExtent();// map the input image through a lookup table and window / level itvtkNew<vtkImageMapToWindowLevelColors> windowLevel;windowLevel->SetWindow(1000);windowLevel->SetLevel(800);windowLevel->SetInputData(imageData);//vtkImageActor: draw an image in a rendered 3D scenevtkNew<vtkImageActor> imageActor;imageActor->SetDisplayExtent(ext[0], ext[1], ext[2], ext[3], ImageSlice, ImageSlice);imageActor->GetMapper()->SetInputConnection(windowLevel->GetOutputPort());// The renderer generates the image which is then displayed on the render window.vtkNew<vtkRenderer> renderer;renderer->AddActor(imageActor);renderer->SetBackground(.2,.2,.2);vtkCamera *cam = renderer->GetActiveCamera();if (cam){// 获取物体在三维空间中的原点,XYZ范围和中心//vtkImageData* idata = reader->GetOutput();vtkImageData* idata = imageData;double* origins = idata->GetOrigin(); // 三维坐标中的起点double* bounds = idata->GetBounds(); // 包围盒的xyz范围double* center = idata->GetCenter(); // 中心cam->SetFocalPoint(center);cam->SetPosition(center[0], center[1], center[2] - bounds[5]); // -1 if medical ?cam->SetViewUp(0, 1, 0);cam->SetClippingRange(0.1,1000);renderer->ResetCamera();}// The render window is the actual GUI window that appears on the computer screenvtkNew<vtkRenderWindow> renderWindow;renderWindow->SetSize(512, 512);renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("Dicom Image");// The render window interactor captures mouse events// and will perform appropriate camera or actor manipulation// depending on the nature of the events.vtkNew<vtkRenderWindowInteractor> interactor;interactor->SetRenderWindow(renderWindow);// This starts the event loop and as a side effect causes an initial render.renderWindow->Render();interactor->Start();
}
主要修改的代码如下:
vtkNew<vtkImageData> imageData;imageData->SetDimensions(512, 512, 10);imageData->SetSpacing(.49, .49, .7);imageData->SetOrigin(0.0, 0.0, 0.0);imageData->AllocateScalars(VTK_SHORT, 1);void *ptr = imageData->GetScalarPointer();size_t bSize = 512 * 512 * 10;FILE* pFile = fopen("D:\\DicomFiles\\test.img","rb+");if (NULL == pFile)return;fread(ptr, sizeof(short), bSize, pFile);fclose(pFile);
SetDimensions 函数主要用来设置图像的长宽高信息
SetSpacing 是像素间距,图像的(512 - 1)* 0.49 就是图像宽的实际尺寸;
SetOrigin 是图像在世界坐标中的位置;
AllocateScalars有两个参数,第一个参数指定数据类型(16bit short);第二个参数1是 一个像素是有一个元素组成(对于BMP位图来说,一个像素是有RGB/RGBA组成的);
AllocateScalars 同时还分配内存空间;
GetScalarPointer函数可以获取分配内存空间的地址;有了地址,有了数据的大小,就可以直接从硬盘读取裸数据了。读取的代码用C语言来写的,这里就不解释了。
运行结果如下:
3 vtkImageData转RGB或RGBA格式
接下来我们增加了个一个Convert2RGB函数,用户将vtkImageData中的数据转换为RGB格式的数据,并保存的硬盘,然后用Mricro打开查看。
完整源代码如下:
#define _CRT_SECURE_NO_WARNINGS#include "vtkImageMapToWindowLevelColors.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkImageData.h"
#include "vtkNew.h"
#include "vtkDICOMImageReader.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkCamera.h"
#include "vtkWindowLevelLookupTable.h"
int ImageSlice = 0;void Convert2RGB(vtkImageData* pData);void main()
{vtkNew<vtkImageData> imageData;imageData->SetDimensions(512, 512, 10);imageData->SetSpacing(.49, .49, .7);imageData->SetOrigin(0.0, 0.0, 0.0);imageData->AllocateScalars(VTK_SHORT, 1);void *ptr = imageData->GetScalarPointer();size_t bSize = 512 * 512 * 10;FILE* pFile = fopen("D:\\DicomFiles\\test.img","rb+");if (NULL == pFile)return;fread(ptr, sizeof(short), bSize, pFile);fclose(pFile);Convert2RGB(imageData);int* ext = imageData->GetExtent();// map the input image through a lookup table and window / level itvtkNew<vtkImageMapToWindowLevelColors> windowLevel;windowLevel->SetWindow(1000);windowLevel->SetLevel(800);windowLevel->SetInputData(imageData);//vtkImageActor: draw an image in a rendered 3D scenevtkNew<vtkImageActor> imageActor;imageActor->SetDisplayExtent(ext[0], ext[1], ext[2], ext[3], ImageSlice, ImageSlice);imageActor->GetMapper()->SetInputConnection(windowLevel->GetOutputPort());// The renderer generates the image which is then displayed on the render window.vtkNew<vtkRenderer> renderer;renderer->AddActor(imageActor);renderer->SetBackground(.2,.2,.2);vtkCamera *cam = renderer->GetActiveCamera();if (cam){// 获取物体在三维空间中的原点,XYZ范围和中心//vtkImageData* idata = reader->GetOutput();vtkImageData* idata = imageData;double* origins = idata->GetOrigin(); // 三维坐标中的起点double* bounds = idata->GetBounds(); // 包围盒的xyz范围double* center = idata->GetCenter(); // 中心cam->SetFocalPoint(center);cam->SetPosition(center[0], center[1], center[2] - bounds[5]); // -1 if medical ?cam->SetViewUp(0, 1, 0);cam->SetClippingRange(0.1,1000);renderer->ResetCamera();}// The render window is the actual GUI window that appears on the computer screenvtkNew<vtkRenderWindow> renderWindow;renderWindow->SetSize(512, 512);renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("Dicom Image");// The render window interactor captures mouse events// and will perform appropriate camera or actor manipulation// depending on the nature of the events.vtkNew<vtkRenderWindowInteractor> interactor;interactor->SetRenderWindow(renderWindow);// This starts the event loop and as a side effect causes an initial render.renderWindow->Render();interactor->Start();
}void Convert2RGB(vtkImageData* pData)
{void *ptr = pData->GetScalarPointer();vtkNew<vtkWindowLevelLookupTable> table;table->SetWindow(1000);table->SetLevel(800);table->Build();table->BuildSpecialColors();long iCount = 512 * 512;void *rgbPtr = malloc(iCount * 3);unsigned char *desPtr = (unsigned char *)rgbPtr;table->MapScalarsThroughTable2(ptr, desPtr, VTK_UNSIGNED_SHORT, iCount, VTK_LUMINANCE, VTK_RGB);FILE* pFile = fopen("color2.img", "wb+");if (!pFile)return;fwrite(rgbPtr, 1, iCount * 3, pFile);fclose(pFile);free(rgbPtr);}
打开源代码所在文件夹,会发现多了一个color2.img,打开Mricro软件,将 color2.img拖到Mricro软件中,发现打开后是乱码,这是由于Mricro软件左侧的参数信息不正确。
将左侧X Y Z分别填入512 512 1
将Data,选中 24-bit rgb,
然后点击菜单中的Header,Save header;
保存完成后,双击 color2.hdr,打开,显示结果如下:
在这里例子中,我们只保存了一张RGB,而图像是有10张的,请自己动手,把10张图像全部保存成为RGB数据,练习一下。
4 练习
(1)用vtkImageData读取一张BMP图像,并显示;
(2)将相机的位置这是在现在位置的反方向,对比下显示结果;
(3)将vtkImageData中的数据重新保存一份,用Mricro软件打开查看是否正确;
总结
相关文章:

004: VTK读入数据---vtkImageData详细说明
VTK医学图像处理---vtkImageData类 目录 VTK医学图像处理---vtkImageData类 简介: 1 Mricro软件的安装和使用 (1) Mricro安装 (2) Mricro转换DICOM为裸数据 2 从硬盘读取数据到vtkImageData 3 vtkImageData转RGB或RGBA格式 4 练习 总结 简介:…...
分割千万级,将大文件分割为小件 csv
依赖 <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.9.0</version></dependency> package com.topnet.controller;import com.topnet.utils.R; import lombok.extern.slf4j.Slf4…...
SQL COUNT() 函数深入解析
SQL COUNT() 函数深入解析 SQL(Structured Query Language)是一种用于管理关系数据库管理系统(RDBMS)的标准编程语言。在SQL中,COUNT() 函数是一个常用的聚合函数,用于计算数据表中的行数或特定列的值数量…...
vue3和vue2的双向绑定原理
Vue 的双向绑定是其核心特性之一,允许数据和视图之间保持同步。在 Vue 2 和 Vue 3 中,双向绑定的实现原理有所不同。以下是两者的原理对比: Vue 2 的双向绑定原理 在 Vue 2 中,双向绑定是通过以下机制实现的: 响应式…...

[C++]刷题
作者主页: 作者主页 本篇博客专栏:C 创作时间 :2024年6月20日 最后: 十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我: 1.一个冷知识: …...

职称评审中,论文发表要求?
无论是医生、教师或其他等职业,职称评审无疑是一个非常重要的环节。而职称评审中的论文发表则是评定我们专业能力的重要一环,可如何才能让自己辛苦撰写的的论文被发表,达到论文发表都有哪些要求呢? 一、选题要新颖 编辑和审稿人…...

连续信号的matlab表示
复习信号与系统以及matlab 在matlab中连续信号使用较小的采样间隔来表四 1.单位阶跃信号 阶跃信号:一个理想的单位阶跃信号在时间 t 0 之前值为0,在 t 0 及之后值突然变为常数 A(通常取 A 1) %matlab表示连续信号,是让信号的采样间隔很小…...
centos7.9搭建mysql5.6主从
mysql5.6 搭建数据库配置主从 搭建数据库 官网下载软件包后上传 基于centos7.9搭建mysql5.6.42 [rootmysql02 ~]# ls anaconda-ks.cfg init.sh MySQL-5.6.42-1.el7.x86_64.rpm-bundle.tar解压 tar -xf MySQL-5.6.42-1.el7.x86_64.rpm-bundle.tar -C /opt/[rootmysql02 ~]…...
C#通过ACE OLEDB驱动程序访问 Access和 Excel
ACE 代表 Access Connectivity Engine。它是 Microsoft 提供的一组组件,用于访问和操作 Microsoft Access 数据库以及其他类似的文件格式,如 Excel 工作簿。ACE 主要包括以下几部分: ACE OLEDB 驱动程序:用于通过 OLE DB 提供程序…...

智能新纪元:GPT-Next引领的AI革命及其跨领域应用
GPT-Next:性能的百倍提升 在当今这个科技日新月异的时代,人工智能(AI)无疑是最具活力和变革性的领域之一。最近,OpenAI在KDDI峰会上宣布了一项激动人心的消息:他们即将推出名为“GPT-Next”的新一代语言模…...

Nexus配置npm私服
1,配置npm-hub 2,配置proxy-npm 3,配置group-npm 4,配置local-npm 5,配置淘宝...

《OpenCV计算机视觉》—— 图像轮廓检测与绘制
文章目录 一、轮廓的检测二、轮廓的绘制图像轮廓检测与绘制的代码实现 三、轮廓的近似 一、轮廓的检测 轮廓检测是指在包含目标和背景的数字图像中,忽略背景和目标内部的纹理以及噪声干扰的影响,采用一定的技术和方法来实现目标轮廓提取的过程注意:做轮…...

Spark-Yarn模式如何配置历史服务器
在Spark程序结束之后我们也想看到运行过程怎么办? Yarn模式下,通过以下步骤配置历史服务器即可: mv spark-defaults.conf.template spark-defaults.conf修改spark-default.conf 文件,配置日志存储路径 spark.eventLog.enabled true spark.…...

Maven的安装
一、安装 压缩包解压完的目录如下所示(此处为绿色免安装版): (其余三个文件是针对Maven版本,第三方软件等简要介绍) 二、环境变量 前提: jdk最低版本为JAVA7(即jdk17)…...

iOS——APP启动流程
APP启动 APP启动主要分为两个阶段:pre-main和main之后,而APP的启动优化也主要是在这两个阶段进行的。 main之后的优化:1. 减少不必要的任务,2.必要的任务延迟执行,例如放在控制器界面等等。 APP启动的大致过程&#…...

LLM模型:代码讲解Transformer运行原理
视频讲解、获取源码:LLM模型:代码讲解Transformer运行原理(1)_哔哩哔哩_bilibili 1 训练保存模型文件 2 模型推理 3 推理代码 import torch import tiktoken from wutenglan_model import WutenglanModelimport pyttsx3# 设置设备为CUDA(如果…...

虚幻引擎VR游戏开发02 | 性能优化设置
常识:VR需要保持至少90 FPS的刷新率,以避免用户体验到延迟或晕眩感。以下是优化性能的一系列设置(make sure the frame rate does not drop below a certain threshold) In project setting-> (以下十个设置都在pr…...

Web应用监控:URL事务监测指标解读
监控易是一款功能强大的IT监控软件,它能够实时监控各种IT资源和应用的运行状态,确保业务的连续性和稳定性。在Web应用监控方面,监控易提供了URL事务监测功能,通过模拟用户访问流程,监测整个事务的执行过程和性能表现。…...

redis之缓存淘汰策略
1.查看redis的最大占用内存 使用redis-cli命令连接redis服务端,输入命令:config get maxmemory 输出的值为0,0代表redis的最大占用内存等同于服务器的最大内存。 2.设置redis的最大占用内存 编辑redis的配置文件,并重启redis服务…...

CMake/C++:一个日志库spdlog
项目仓库 GitHub - gabime/spdlog: Fast C logging library.Fast C logging library. Contribute to gabime/spdlog development by creating an account on GitHub.https://github.com/gabime/spdlog 知乎参考贴 https://zhuanlan.zhihu.com/p/674073158 先将仓库clone一下 然…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...