医学图像的浏览和内部分析是很常见也很重要的功能,我们不仅可以从矢状面、冠状面和轴状面这样的切面去看,还可以从任意切面去看。在VTK术语中,切面(切片)就是图像数据。

vtkImageReslice

vtkImageReslice,功能非常强大,有“瑞士军刀”的美誉。它不仅可以提取切片,还有图像旋转,翻转,重采样,变形等功能,并且效率还很高。这里只用到它的提取功能。
切片提取
切片提取的关键是要给出ResliceAxes,实际上,它是一个4X4的矩阵。我们可以这样来理解:把这个矩阵看作是新坐标系在原坐标下的坐标表示,一个齐次坐标系。前三列分别表示新坐标系下x、y、z的向量坐标,第四列表示新坐标系下原点的坐标。例如:
0, 0, -1, 6
1, 0, 0, 0
0, -1, 0, 0
0, 0, 0, 1
这个矩阵表示了在新坐标系下,x方向向量为(0, 1, 0),y方向向量为(0, 0, -1),z方向向量为(-1, 0, 0)和原点坐标为(6, 0, 0)矩阵。需要注意到是x, y, z三个向量要符合右手法则。
下面两种写法,作用一样:
写法一:

 auto resliceAxes = vtkSmartPointer<vtkMatrix4x4>::New();auto ImageReslice = vtkSmartPointer<vtkImageReslice>::New();ImageReslice->SetResliceAxes(resliceAxes);

写法二:

 double x[3] = { 1, 0, 0 };double y[3] = { 0, 1, 0 };double z[3] = { 0, 0, 1 };double origin[3] = { 1, 0, 0 };ImageReslice->SetResliceAxesDirectionCosines(x, y, z);ImageReslice->SetResliceAxesOrigin(origin);

脑部CT图像

ResliceImage.cxx

#include "vtkSmartPointer.h"
#include "vtkMatrix4x4.h"
#include "vtkDICOMImageReader.h"
#include "vtkImageData.h"
#include "vtkImageReslice.h"
#include "vtkLookupTable.h"
#include "vtkImageMapToColors.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyleImage.h"
#include "vtkCommand.h"class vtkImageInteractionCallback : public vtkCommand
{public:static vtkImageInteractionCallback* New(){return new vtkImageInteractionCallback;}vtkImageInteractionCallback(){this->Slicing = 0;this->ImageReslice = nullptr;this->Interactor = nullptr;}void SetImageReslice(vtkImageReslice* reslice){this->ImageReslice = reslice;}void SetMapToColors(vtkImageMapToColors* colors){this->MapToColors = colors;}void SetInteractor(vtkRenderWindowInteractor* interactor){this->Interactor = interactor;}void SetRenderWindow(vtkRenderWindow* window){this->RenderWindow = window;}void Execute(vtkObject* caller, unsigned long eventId, void* callData) override{int lastPos[2], curPos[2];this->Interactor->GetLastEventPosition(lastPos);this->Interactor->GetEventPosition(curPos);if (eventId == vtkCommand::LeftButtonPressEvent){this->Slicing = 1;}else if (eventId == vtkCommand::LeftButtonReleaseEvent){this->Slicing = 0;}else if (eventId == vtkCommand::MouseMoveEvent){if (this->Slicing){int deltaY = lastPos[1] - curPos[1];this->ImageReslice->Update();double spacing = this->ImageReslice->GetOutput()->GetSpacing()[2];vtkMatrix4x4* matrix = this->ImageReslice->GetResliceAxes();double point[4], center[4];point[0] = 0.0;point[1] = 0.0;point[2] = spacing * deltaY;point[3] = 1.0;matrix->MultiplyPoint(point, center);matrix->SetElement(0, 3, center[0]);matrix->SetElement(1, 3, center[1]);matrix->SetElement(2, 3, center[2]);this->MapToColors->Update();this->OutputImageData = this->MapToColors->GetOutput();this->Interactor->Render();}else{vtkInteractorStyle* style = vtkInteractorStyle::SafeDownCast(this->Interactor->GetInteractorStyle());if (style)style->OnMouseMove();}}}private:int Slicing;vtkImageReslice* ImageReslice;vtkImageMapToColors* MapToColors;vtkRenderWindowInteractor* Interactor;vtkRenderWindow* RenderWindow;vtkImageData* OutputImageData;
};int main(int argc, char* argv[])
{if (argc < 2){std::cout << "Usage: " << argv[0] << " DicomDirectory" << std::endl;return EXIT_FAILURE;}auto reader = vtkSmartPointer<vtkDICOMImageReader>::New();reader->SetDirectoryName(argv[1]);reader->Update();int extent[6];double spacing[3];double origin[3];double center[3];reader->GetOutput()->GetExtent(extent);reader->GetOutput()->GetSpacing(spacing);reader->GetOutput()->GetOrigin(origin);center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);static double sagittalElements[16] = {0, 0,-1, 0,1, 0, 0, 0,0,-1, 0, 0,0, 0, 0, 1 };static double cornalElements[16] = {1, 0, 0, 0,0, 0, 1, 0,0, -1,0, 0,0, 0, 0, 1 };static double axialElements[16] = {1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,0, 0, 0, 1 };static double obliqueElements[16] = {1, 0, 0, 0,0, 0.866025, -0.5, 0,0, 0.5, 0.866025, 0,0, 0, 0, 1 };auto resliceAxes = vtkSmartPointer<vtkMatrix4x4>::New();resliceAxes->DeepCopy(axialElements);resliceAxes->SetElement(0, 3, center[0]);resliceAxes->SetElement(1, 3, center[1]);resliceAxes->SetElement(2, 3, center[2]);double x[3] = { 1, 0, 0 };double y[3] = { 0, 1, 0 };double z[3] = { 0, 0, 1 };auto ImageReslice = vtkSmartPointer<vtkImageReslice>::New();ImageReslice->SetInputConnection(reader->GetOutputPort());ImageReslice->SetOutputDimensionality(2);
#if 0ImageReslice->SetResliceAxes(resliceAxes);
#elseImageReslice->SetResliceAxesDirectionCosines(x, y, z);ImageReslice->SetResliceAxesOrigin(center);
#endifImageReslice->SetInterpolationModeToLinear();auto lookupTable = vtkSmartPointer<vtkLookupTable>::New();lookupTable->SetRange(0, 2000);lookupTable->SetValueRange(0.0, 1.0);lookupTable->SetSaturationRange(0.0, 0.0);lookupTable->SetRampToLinear();lookupTable->Build();auto mapToColors = vtkSmartPointer<vtkImageMapToColors>::New();mapToColors->SetLookupTable(lookupTable);mapToColors->SetInputConnection(ImageReslice->GetOutputPort());mapToColors->Update();auto imageActor = vtkSmartPointer<vtkImageActor>::New();imageActor->GetMapper()->SetInputConnection(mapToColors->GetOutputPort());auto renderer = vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(imageActor);auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(renderer);auto imageStyle = vtkSmartPointer<vtkInteractorStyleImage>::New();auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();interactor->SetInteractorStyle(imageStyle);interactor->SetRenderWindow(renderWindow);interactor->Initialize();auto callback = vtkSmartPointer<vtkImageInteractionCallback>::New();callback->SetImageReslice(ImageReslice);callback->SetMapToColors(mapToColors);callback->SetInteractor(interactor);callback->SetRenderWindow(renderWindow);imageStyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);imageStyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);imageStyle->AddObserver(vtkCommand::MouseMoveEvent, callback);interactor->Start();return EXIT_SUCCESS;
}

Example Download

Ref

vtkImageReslice Class Reference
VTK修炼之道26:图像基本操作_三维图像切片提取

VTK笔记——医学图像的切片提取(vtkImageReslice)相关推荐

  1. VTK修炼之道26:图像基本操作_三维图像切片提取

    1.三维图像切片提取 切片是指三维图像中的一个切面对应的图像.切面可以是过图像内部一点且平行于XY.YZ.XZ平面的平面,也可以是任意的过三维图像内部一点任意方向的平面.通过提取切片可以方便的浏览和分 ...

  2. Go语言学习笔记-数组、切片、map

    Go语言学习笔记-数组.切片.map 数组:同一数据类型元素的集合.是值类型,长度固定无法修改 声明格式:var 数组名字 [元素数量] 数据类型 var arr [3] int //声明定义了一个长 ...

  3. VTK笔记——插值样条曲线采样

    有时候我们想通过在样条曲线上得到更多的点,比如用这些点来与另一条曲线连通生成三角条,让曲线在可视化的时候分辨率更高,等等,就需要用到曲线插值采用.最常见的是样条曲线插值采样. 曲线已经有了情况下(关于 ...

  4. VTK笔记-相机vtkCamera-投影方式与裁剪范围

    投影方式中物体在View上的投影位置   在之前对多边形数据进行裁剪时<VTK笔记-裁剪分割-不规则闭合圈选裁剪-vtkImplicitSelectionLoop类>,显示的下图的效果:在 ...

  5. VTK笔记-计算MPR切面-vtkImageReslice类

    MPR   MPR(Multi-planar Reformation),多平面重建:多平面重建是将扫描范围内所有的轴位图像叠加起来,再对某些标线标定的重组线所指定的组织进行冠状位.矢状位.任意角度斜位 ...

  6. VTK笔记-计算MPR切面-vtkImageReslice输出视口设置

      设定的坐标点,vtkImageReslice生成的切面是一个无限大的二维图像,图像的中心点是设定的坐标点,在二维图像中是坐标原点(0,0),根据需要可以设定二维图像左下角的坐标位置,也可以设定像素 ...

  7. VTK笔记-CT图像获取皮肤等值面-vtkContourFilter类的使用

    文章目录 vtkContourFilter SetValue GenerateValues SetValue与GenerateValues的区别与联系 实例 代码 各个对象的关系图 运行效果 引用 本 ...

  8. VTK笔记-裁剪分割-几何裁剪-vtkClipPolyData

    什么是裁剪分割   VTK加载二维数据和三维数据,我们通常观察到的是三视图图像,或者是vtkImageReslice获取到的转换矩阵对应的观察点三视图或者是斜平面图像,想要看到图像中间部分的渲染结果就 ...

  9. VTK笔记-图像相关-vtkImageViewer2类

    vtkImageViewer2   vtkImageViewer2类用来显示二维图像:vtk的版本更新,使用vtkImageViewer2替代vtkImageViewer类:   vtkImageVi ...

最新文章

  1. python写文件读文件-Python 实例:读写文件
  2. WEB Struts2 中OGNL的用法
  3. JAVA多线程学习(一)
  4. Linux系统优化脚本
  5. fetch用英语解释_初中英语重点知识点,初中三年必须掌握!
  6. 视频增强之“动态范围扩展”HDR技术漫谈
  7. Linux yum更新源url
  8. 家有路由器,为什么会出现网络拒绝接入而无法上网的情况呢?
  9. advanced installer 使用常见问题整理
  10. adb 驱动安装说明文档
  11. windows服务器重装教程,Win10系统怎么重装?Win10系统重装教程
  12. 当初为了有机会进大厂,狠心复习了这9门核心知识点,熬夜整理成思维导图送给大家
  13. 蒙特卡洛方法求圆周率
  14. Win7中双击bat文件变成打开文本编辑器后如何恢复
  15. MACD多周期共振系统TB源码
  16. oracle 百分位数,Oracle分析函数PERCENTILE_CONT
  17. PHP CURL实现单线程、多线程方法
  18. ElasticSearch使用(嵌套查询、嵌套高亮)
  19. JSFL_图片转换SWF导出
  20. 大学计算机操作题模拟,大学计算机一级模拟操作题1

热门文章

  1. matlab学习创建变量定义函数
  2. alin的学习之路:面试题 数据库相关
  3. AndroidStudio 3.0.1 cmake安装
  4. mysql_08_ yum(dnf)安装
  5. win10自带远程桌面连接linux系统时崩溃的问题
  6. Microsoft Exchange Server 2007: Tony Redmond's Guide to Successful Implementation
  7. 鄂马赛记 | 跑步就跑步,跑什么马拉松?
  8. 湘鄂情欲加码大数据 若定增失败将变卖资产
  9. 为什么手机一开机,就有Powered by Android
  10. 我们是如何改进YOLOv3进行红外小目标检测的?