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


本文中关于等值面的处理的内容大部分转载于CSDN博主「知乎:C加加辅导袁老师」的原创文章《vtkContourFilter等值面(线)》;
原文链接:https://blog.csdn.net/calmreason/article/details/102959607

vtkContourFilter

过滤器vtkContourFilter用于从数据中抽取一系列等值面。
抽取轮廓的操作对象是标量数据。其思想是:将数据集中标量值等于某一指定恒量值的部分提取出来。对于3D的数据集而言,产生的是一个等值面;对于2D的数据集而言,产生的是一个等值线。其典型的应用有气象图中的等温线、地形图中的等高线。对于医学数据而言,不同的标量值代表的是人体的不同部分,因而可以分别提取出人的皮肤或骨头。
提取等值线需要vtkContourFilter过滤器,输入数据源,设置等值线,更新即可得到等值线数据。
vtkContourFilter 可以接受任意数据集类型作为输入,因而具有 一般性。使用vtkContourFilter 时,除了需要设置输入数据集外,还需要指定一个或多个用于抽取的标量值。
抽取等值面的功能可以使用如下两种方法进行实现:

SetValue

  1. 逐个设置抽取值。该方法有个两个参数:第一个参数是抽取值的索引号,表示第几个 抽取值。索引号从0开始计数;第二个参数就是指定的抽取值。
  2. SetValue(i,value) i表示第几条等值线,从0开始计算,value表示等值线的值。
  3. 多边形的每个点都有一个属性值,两个相邻的属性值之间要先通过插值,再把这些属性值作为该函数的输入。
  4. 如SetValue(0,5) 画一条等值为5的等值线两个相邻的点的属性值为3和6,则先插值为(3,4,5,6),所以该先应该经过这条边的2/3处。

GenerateValues

  1. 自动产生一系列抽取值。该方法有三个参数:第一个参数是抽取值的个数,后面两个参数是抽取值的取值范围。
    例如: vtkSmartPointer contours = vtkSmartPointer::New();
    contours->GenerateValues(5.0, 0.0, 1.2);
    最终产生的抽取值为0.0, 0.3, 0.6, 0.9和1.0,这是一个等差数列。

SetValue与GenerateValues的区别与联系

这两个函数的不同之处在于SetValue设置一条等值线值,而GenerateValues对应n条等值线的值,同时数量n包括两个边界值,其余n-2条等值线的值自动按照线性关系产生。
SetValue和GenerateValues函数根据先后调用关系产生覆盖,即后调用的函数产生的等值线可能覆盖掉先调用函数产生的等值线,这与等值线的条数(GetNumberOfContours)相关。
例如:首先调用GenerateValues(3, 100, 300)产生3条等值线,分别为100、200、300;然后调用SetValue(0, 125),则最终效果为共有3条等值线,分别为125、200、300;如果改为调用SetValue(3, 400),则最终效果为共有4条等值线,分别为100、200、300、400。
SetValue一般用于覆盖某一条已经存在的等值线,或者增加一条等值线;GenerateValues一般重新设置等值线的条数。
等值线示例

m_contourFilter->SetValue(0, 1);// 设置值为1的等值线
m_contourFilter->SetValue(1, 2);// 设置值为2的等值线
m_contourFilter->SetValue(2, 3);// 设置值为3的等值线
m_contourFilter->SetValue(3, 4);// 设置值为4的等值线
m_contourFilter->SetValue(4, 5);// 设置值为5的等值线
m_contourFilter->SetValue(5, 6);// 设置值为6的等值线
m_contourFilter->SetValue(6, 7);// 设置值为7的等值线
m_contourFilter->Update(); // 计算出轮廓数据

不同值之间如果差距过大,中间总是会被插入对应的等值线:
在这里插入图片描述
如下图所示,0和5之间插入了4条等值线。这个时候等值线已经无法体现轮廓的效果。在这里插入图片描述

实例

具体步骤:
1.使用类vtkVolume16Reader读取一系列二维切片文件:quarter.1,quarter.2…quarter.93;
2.使用类vtkContourFilter获取皮肤和骨骼的等值面数据;
3.使用类vtkPolyDataNormals对锐边缘进行处理;
4.使用类vtkOutlineFilter生成数据外部轮廓的正方体边缘;
5.渲染管线执行;

代码

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkPolyDataMapper.h"
#include "vtkVolume16Reader.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkPolyDataNormals.h"
#include "vtkContourFilter.h"

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;

int main()
{
	// 加载图像数据
	vtkVolume16Reader *v16 = vtkVolume16Reader::New();
	v16->SetDataDimensions(64, 64);
	v16->SetImageRange(1, 93);
	v16->SetDataByteOrderToLittleEndian();
	v16->SetFilePrefix("D:\\headsq\\quarter");
	v16->SetDataSpacing(3.2, 3.2, 1.5);
	// 获取等值面
	vtkContourFilter *skinExtractor = vtkContourFilter::New();
	skinExtractor->SetInputConnection(v16->GetOutputPort());
	skinExtractor->SetValue(0, 1150);
	// 是一个过滤器Filter,用来计算法向量,对锐边缘(sharp Edge)进行处理
	vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
	skinNormals->SetInputConnection(skinExtractor->GetOutputPort());
	skinNormals->SetFeatureAngle(60.0);
	vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
	skinMapper->SetInputConnection(skinNormals->GetOutputPort());
	skinMapper->ScalarVisibilityOff();
	vtkActor *skinActor = vtkActor::New();
	skinActor->SetMapper(skinMapper);
	// 绘制外部轮廓的正方体
	vtkOutlineFilter *outlineData = vtkOutlineFilter::New();
	outlineData->SetInputConnection(v16->GetOutputPort());
	vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
	mapOutline->SetInputConnection(outlineData->GetOutputPort());
	vtkActor* outline_actor = vtkActor::New();
	outline_actor->SetMapper(mapOutline);
	outline_actor->GetProperty()->SetColor(0, 0, 0);

	vtkCamera *aCamera = vtkCamera::New();
	aCamera->SetViewUp(0, 0, -1);
	aCamera->SetPosition(0, 1, 0);
	aCamera->SetFocalPoint(0, 0, 0);
	aCamera->ComputeViewPlaneNormal();
	aCamera->Dolly(1.5);

	vtkRenderer *aRender = vtkRenderer::New();
	aRender->AddActor(outline_actor);
	aRender->AddActor(skinActor);
	aRender->SetActiveCamera(aCamera);
	aRender->ResetCamera();
	aRender->SetBackground(1, 1, 1);
	aRender->ResetCameraClippingRange();
	vtkRenderWindow *renWin = vtkRenderWindow::New();
	renWin->AddRenderer(aRender);
	renWin->SetSize(640, 480);

	vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
	iren->SetRenderWindow(renWin);

	iren->Initialize();
	iren->Start();
	system("pause");
	return 0;
}

各个对象的关系图

vtkVolume16Reader
vtkContourFilter
vtkOutlineFilter
vtkPolyDataNormals
vtkPolyDataMapper
vtkPolyDataMapper

运行效果

当skinExtractor->SetValue()函数设置为(0,500)时,运行结果如下图:
在这里插入图片描述
当skinExtractor->SetValue()函数设置为(0,500)时,运行结果如下图:
在这里插入图片描述
文中使用到的图像资源在链接:https://pan.baidu.com/s/1OMBSN69bMj0hYU_1qg_yxw 提取码:yggt

引用

1.《医学图像编程技术》第2章 范例;

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值