基于VTK与Qt的体绘制程序

分类: VTK Qt Volume Rendering C&C++ 2013-06-10 09:17 3434人阅读 评论(13) 收藏 举报

目录(?)[+]

1       基于VTK与Qt的体绘制程序

1.1     体绘制介绍

体绘制(Volume Rendering)是一种从离散三维数据场获得二维投影图像的技术。体绘制在医学成像和科学可视化当中有着广泛应用。用于体绘制的数据集也称为体数据(Volume Data)。典型的三维体数据是通过 CT、MRI等成像技术采集的一组二维切片图像。通常这些图像都是按照某种规则(如每毫米一个切面)采集并重建而成,并有着相同数量的像素。这种体数据是规则的立体晶格,每个体数据的元素(又称为体素,Voxel)由一个通过采样周围相邻区域的体素获得的采样值来表示。

体绘制技术可以根据是否提取曲面分为直接体绘制和间接体绘制(又称为面绘制)两大类。间接体绘制是先从体数据中提取等值面,然后绘制等值面组成的多边形网格;直接体绘制则是将体数据直接作为一个离散三维数据场来绘制。而直接体绘制则直接从体数据中通过颜色与不透明度映射来生成三维数据集的二维投影图像。相对于间接体绘制来说,直接体绘制具有更大的优势,也就是不需要生成中间图元,直接对体数据进行成像,显示出全部的数据信息并且不会造成数据的丢失,而且成像的效果好于面绘制的结果,对人体内部的组织信息能够呈现出体数据更精细的显示结果,具有高度的保真性。由于直接体绘制是目前体绘制技术的主流,以下提到的体绘制都是指直接体绘制。

体绘制的更多信息,可参考:

体绘制(Volume Rendering)概述之1:什么是体绘制

http://blog.csdn.net/liu_lin_xm/article/details/4850575

体绘制(Volume Rendering)概述之2:体数据详解

http://blog.csdn.net/liu_lin_xm/article/details/4850593

1.2     传递函数

为了绘制三维体数据的二维投影,需要为每个体素定义不透明度与颜色。这通常由称为传递函数(Transfer Function)的映射来实现。传递函数为每个可能的体素定义相应的不透明度与颜色值。在体绘制过程中,体数据首先要经过传递函数,将测量得到的灰度值映射为用于显示的不透明度值和颜色值,然后通过光线投射法或者其它体绘制算法绘制出一种根据体数据中所有体素的颜色与不透明度叠加而成的具有立体感的投影图像。

体绘制时,每个采样值都必须映射为不透明度与颜色。这种从体素到不透明度与颜色的映射是通过传递函数来实现的。传递函数可以是简单的线性函数、分段线性函数或者任意的表。

在VTK中,传递函数由颜色传递函数(vtkColorTransferFunction)与不透明度传递函数(vtkPiecewiseFunction)两个类来处理。

1.3     光线投射算法

光线投射法(Volume Ray Casting)可以直接从渲染方程(RenderingEquation)得到。这种技术可以提供非常高的成像质量,通常认为这是图像质量最高的方法。但由于此算法需要需要遍历每个体素,计算复杂度较高。为了提高算法的绘制速度,研究者先后提出了很多改进技术,如采用可以减少投射光线数量的自适应图形采样技术,以及可以减少不必要采样点的空间跳跃技术。

典型的光线投射法包含四个步骤,如下图:

·       投射光线。对最终图像中的每个像素,投射一束沿着视线的光线穿过体数据。在这一阶段,通过将体数据看作被一个基本几何原素(通常是立方体)包围着,并利用这个几何原素的边界来截断投射的光线。

·       采样。沿着体数据内的一段视线,等距离地采样一组点。通常体数据没有与视线对齐在一直线上,因此要对所视线经过的采样点按其周围的体素值采样。这通常需要对采样点周围的体素进行三线性插值(Trilinearly Interpolate)。

·       着色。先对每个采样点分别计算梯度。这些梯度代表了体数据中局部表面的方向。然后根据其方向与场景中的光源对采样点着色,即加上颜色与光照。

·       混合。在所有采样点都着色之后,沿着视线混合在一起,就得到当前正在处理的像素的最终颜色值。计算混合的方法是从绘制方程推导得到的,这类似于在投影仪上将幻灯片叠加在一起的效果。混合方法包括从后向前混合与从前向后混合两种。从后向前混合是从离观察者最远的采样点开始沿着视线向前混合,这样可以保证体数据中被遮蔽的部分不会影响最终得到的像素。

光线投射算法的更多细节,可参考:

体绘制(Volume Rendering)概述之3:光线投射算法(Ray Casting)原理和注意要点

http://blog.csdn.net/liu_lin_xm/article/details/4850609

体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码

http://blog.csdn.net/liu_lin_xm/article/details/4850630

GPU raycasting tutorial

http://www.daimi.au.dk/~trier/?page_id=98

1.4     基于VTK与Qt的体绘制程序

以下是本文作者最近写的一个基于VTK与Qt的体绘制程序:

https://bitbucket.org/lsz/volume-renderer/

源代码在VolumeRenderer目录下。数据文件在data目录下。更多信息见readme.txt。

这个程序使用了VTK的vtkMetaImageReader和vtkSmartVolumeMapper来分别读取和绘制体数据。程序中还是用了部分来自CTK (The Common Toolkit, http://www.commontk.org/)的控件。开源的体绘制软件3D Slicer (http://www.slicer.org/)中也用到了这些CTK控件。

以下是程序中用于读取体数据的代码。

// read Meta Image (.mhd or .mha) files

auto reader =vtkSmartPointer<vtkMetaImageReader>::New();

reader->SetFileName(filename_str);

这里采用了vtkMetaImageReader类来读取UNC Meta Image格式的体数据头文件。UNC Meta Image格式的说明,可参考vtkMetaImageReader的类描述:

http://www.vtk.org/doc/release/6.1/html/classvtkMetaImageReader.html

上面的auto关键字是C++11标准的类型推导,编译器自动根据赋值表达式的类型来确定需要声明的变量类型。

vtkSmartPointer是VTK的智能指针,会自动维护所管理指针的引用计数。当智能指针析构时如果其所管理的指针的引用计数为零,则释放其管理的指针指向的内存。C++11标准的std::shared_ptr以及Qt中的QSharedPointer也是类似的智能指针。不同的是,vtkSmartPointer专门用于VTK类(继承自vtkObjectBase的类),而std::shared_ptr与QSharedPointer则是通用的智能指针。

以下是程序中选择体绘制算法的代码。

// The mapper that renders the volume data.

auto volumeMapper =vtkSmartPointer<vtkSmartVolumeMapper>::New();

volumeMapper->SetRequestedRenderMode(vtkSmartVolumeMapper::GPURenderMode);

volumeMapper->SetInputConnection(shiftScale->GetOutputPort());

这里采用了vtkSmartVolumeMapper类,并将其绘制模式设置为vtkSmartVolumeMapper::GPURenderMode。在此GPU绘制模式下,vtkSmartVolumeMapper实际上使用vtkGPUVolumeRayCastMapper类来进行基于GPU的体绘制。

窗口右边的控件是CTK(www.commontk.org)库中的ctkVTKVolumePropertyWidget体数据属性控件。这个控件可用于设置VTK的vtkPiecewiseFunction(对应窗口右上方的控件)与vtkColorTransferFunction(对应窗口右下方的控件)。vtkPiecewiseFunction与vtkColorTransferFunction这两个类是VTK中用于指定传递函数的类。通过ctkVTKVolumePropertyWidget控件,我们就可以手动调节传递函数,从而探究体数据中我们感兴趣的信息。

此程序在VisualStudio 2012中编写,使用了VTK 6.0与Qt 4库,项目通过CMake来配置。编译方法,首先通过CMake生成Visual Studio项目文件,然后以Visual Studio打开生成的项目文件,编译并运行其中的VolumeRenderer项目。

VTK与Qt开发的更多信息,可参考

基于VTK的Qt应用程序开发

http://blog.csdn.net/www_doling_net/article/details/8668870

基于VTK与Qt的体绘制程序相关推荐

  1. 基于VTK的Qt应用程序开发

    分类: VTK应用示例 2013-03-13 15:51 6622人阅读 评论(25) 收藏 举报 VTKQtCMake 目录(?)[+] VTK附带的程序示例中大多是基于控制台的,作为可视化开发工具 ...

  2. 基于VTKITK的Qt应用程序开发

    关于VTK与Qt整合的程序示例,我们在博文(点击这里查看)里面已经讲得相当详细了.总而言之,言而总之,不外乎先写CMakeLists.txt脚本,然后用CMake Configure,再Generat ...

  3. 基于VTK的MFC应用程序开发(2)

    基于VTK的MFC应用程序开发(2) 分类: VTK应用示例 2013-03-29 13:03 6647人阅读 评论(18) 收藏 举报 MFCVTK图像重采样 目录(?)[+] 现在基于VTK的MF ...

  4. 基于VTK的MFC应用程序开发(1)

    基于VTK的MFC应用程序开发(1) 分类: VTK应用示例 2013-03-24 22:35 4195人阅读 评论(28) 收藏 举报 CMakeVTKMFC 目录(?)[+] 提到MFC一般都不陌 ...

  5. 基于VTK的MFC应用程序开发(3)

    基于VTK的MFC应用程序开发(3) 分类: VTK应用示例 2013-05-17 13:37 3307人阅读 评论(23) 收藏 举报 目录(?)[+] 之前介绍了基于VTK的单文档应用程序开发,并 ...

  6. qt控制程序打开记事本_基于QT记事本应用程序开发.doc

    基于QT记事本应用程序开发 基于QT记事本应用程序开发 [摘要]本文通过对嵌入式Linux和Qt的分析,利用Qt在源代码级上能够实现跨平台特性,在源代码开放的Linux操作系统上,根据嵌入式应用的特点 ...

  7. VTK:利用qt实现体绘制剪裁

    看到有人问体绘制切割,正好早上起的比较早,写一个体绘制切割的demo. VTK:利用qt实现体绘制剪裁 做体绘制渲染一定少不了交互剪裁的功能.一般有两种方式: 搞一个包围盒,移动包围盒实现体渲染的剪裁 ...

  8. 基于C++的Qt网络编程——基于 IP 多播的网络会议程序

    目录 一.实验题目 二.实验目的 三.总体设计 1.实验原理 2.设计步骤 四.详细设计 1.程序流程图 2.实验代码(部分) 五.实验结果与分析 六.小结与心得体会 一.实验题目 基于 IP 多播的 ...

  9. VTK与Qt整合的示例

    VTK与Qt整合的示例 VTK附带的程序示例中大多是基于控制台的,作为可视化开发工具包,VTK也可以与很多流行的GUI开发工具整合,比如MFC.Qt(题外话:Qt已经被Digia从诺基亚手中收购了,Q ...

最新文章

  1. HQL语句中数据类型转换,及hibernate中createQuery执行hql报错
  2. 【PC工具】智能抠图软件,绿色免安装抠图神奇抠图工具
  3. Java基础提升篇:equals()与hashCode()方法详解
  4. MOBA项目定点数的一个想法
  5. boost::geometry::util::calculation_type用法的测试程序
  6. python中硬要写抽象类和抽象方法
  7. netflix_学习Netflix管理员–第1部分
  8. decimal类型对象里面定义什么类型_奥斯塔罗 单身开启桃花雷达 现阶段的我适合什么类型的对象?...
  9. (JAVA)获取对象
  10. (软件工程复习核心重点)第十章面向对象设计-第一节:面向对象设计的基本概念与准则
  11. 1014-新浪微博(数据 cell )
  12. 荐书丨如何快速成为150万+小程序开发者中的一员
  13. HDU 1556 Color the ball 线段树
  14. Mybatis开启日志
  15. python生成微信小程序码
  16. Fully Convolutional Cross-Scale-Flows for Image-based Defect Detection
  17. 《代码大全2》第3章 三思而后行,前期准备
  18. 柴胡加龙骨牡蛎汤去大黄合当归芍药散治顽固心悸案(李跃海)
  19. 豪拒60亿美元,天真的程序员CEO最终被自己的公司解雇
  20. 北师大珠海分校2017国庆欢乐赛题解

热门文章

  1. 做有挑战的事情就行了~
  2. MONO源码编译笔记-版本:unity-2018.4-mbe
  3. C#抽象类与接口的区别【转】
  4. LUA GC 简单测试
  5. vector 用法小例子
  6. HDU5511 : Minimum Cut-Cut
  7. Win10光驱不见了
  8. IOS对plist配置文件的读写操作
  9. style.display,有点问题
  10. linux sed命令的用法