基于VTK9.3.0+Visual Studio2017 c++实现DICOM影像MPR多平面重建+V R体绘制4个视图展示功能的实现

开源库:VTK9.3.0

开发工具:Visual Studio2017

开发语言:C++

实现过程:

class vtkImageInteractionCallback : public vtkCommand
{
public:
	static vtkImageInteractionCallback* New()
	{
		return new vtkImageInteractionCallback();
	}

	vtkImageInteractionCallback()
		: ImageReslice(nullptr), Slicing(0) {}

	void SetImageReslice(vtkImageReslice* reslice) { this->ImageReslice = reslice; }

	virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) override
	{
		vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);
		if (!interactor) return;

		int x, y;
		interactor->GetEventPosition(x, y);

		if (eventId == vtkCommand::MouseMoveEvent)
		{
			if (this->Slicing)
			{
				this->ProcessSlicing(interactor, x, y);
			}
		}
		else if (eventId == vtkCommand::LeftButtonPressEvent)
		{
			this->Slicing = 1;
		}
		else if (eventId == vtkCommand::LeftButtonReleaseEvent)
		{
			this->Slicing = 0;
		}
	}

protected:
	void ProcessSlicing(vtkRenderWindowInteractor* interactor, int x, int y)
	{
		// 获取当前切片的中心位置
		double sliceCenter[3];
		this->ImageReslice->GetOutput()->GetCenter(sliceCenter);

		// 获取鼠标移动的增量
		int lastX = interactor->GetLastEventPosition()[0];
		int lastY = interactor->GetLastEventPosition()[1];
		int deltaY = y - lastY;

		// 根据移动的方向和增量调整切片位置
		double newSlicePosition = sliceCenter[2] + deltaY * 0.1; // 比例因子可以调整
		sliceCenter[2] = newSlicePosition;

		// 设置新的切片位置
		this->ImageReslice->SetResliceAxesOrigin(sliceCenter);
		interactor->Render(); // 渲染更新后的图像
	}

	vtkImageReslice* ImageReslice;
	int Slicing;
};

void initImageActor(double* Matrix, double* center, vtkSmartPointer<vtkImageCast> pImageCast,
	vtkSmartPointer<vtkImageReslice> imageReslice, vtkSmartPointer<vtkImageActor> actor)
{
	vtkSmartPointer<vtkMatrix4x4> AxialResliceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
	AxialResliceMatrix->DeepCopy(Matrix);

	AxialResliceMatrix->SetElement(0, 3, center[0]);
	AxialResliceMatrix->SetElement(1, 3, center[1]);
	AxialResliceMatrix->SetElement(2, 3, center[2]);

	imageReslice->SetInputConnection(pImageCast->GetOutputPort());
	imageReslice->SetOutputDimensionality(2);
	imageReslice->SetResliceAxes(AxialResliceMatrix);
	imageReslice->SetInterpolationModeToLinear();
	imageReslice->Update();

	actor->GetMapper()->SetInputConnection(imageReslice->GetOutputPort());
	actor->SetPosition(0, 0, 0);
}

void addImageInteractionCallback(vtkRenderWindowInteractor* interactor, vtkImageReslice* imageReslice)
{
	vtkSmartPointer<vtkImageInteractionCallback> callback = vtkSmartPointer<vtkImageInteractionCallback>::New();
	callback->SetImageReslice(imageReslice);

	vtkSmartPointer<vtkInteractorStyleImage> imagestyle = vtkSmartPointer<vtkInteractorStyleImage>::New();
	interactor->SetInteractorStyle(imagestyle);

	imagestyle->AddObserver(vtkCommand::MouseMoveEvent, callback);
	imagestyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
	imagestyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);
}

int main()
{
	vtkSmartPointer<vtkImageReslice> pImageResliceX = vtkSmartPointer<vtkImageReslice>::New();
	vtkSmartPointer<vtkImageReslice> pImageResliceY = vtkSmartPointer<vtkImageReslice>::New();
	vtkSmartPointer<vtkImageReslice> pImageResliceZ = vtkSmartPointer<vtkImageReslice>::New();

	vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
	reader->SetDirectoryName("D:\\image\\images\\011\\CT\\20200115\\67728\\1.3.46.670589.33.1.63714685715192329600004.5577472948825480582");
	reader->Update();

	int extent[6];
	double spacing[3];
	double origin[3];

	reader->GetOutput()->GetExtent(extent);
	reader->GetOutput()->GetSpacing(spacing);
	reader->GetOutput()->GetOrigin(origin);

	double center[3];
	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]);

	double Axial[16] = {
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1 };
	double Coronal[16] = {
		1, 0, 0, 0,
		0, 0, -1, 0,
		0, 1, 0, 0,
		0, 0, 0, 1 };
	double Sagittal[16] = {
		0, 0, 1, 0,
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 0, 1 };

	vtkSmartPointer<vtkImageCast> pImageCast = vtkSmartPointer<vtkImageCast>::New();
	pImageCast->SetInputConnection(reader->GetOutputPort());
	pImageCast->SetOutputScalarTypeToUnsignedChar();
	pImageCast->ClampOverflowOn();
	pImageCast->Update();

	vtkSmartPointer<vtkImageActor> pImageActorX = vtkSmartPointer<vtkImageActor>::New();
	vtkSmartPointer<vtkImageActor> pImageActorY = vtkSmartPointer<vtkImageActor>::New();
	vtkSmartPointer<vtkImageActor> pImageActorZ = vtkSmartPointer<vtkImageActor>::New();

	initImageActor(Axial, center, pImageCast, pImageResliceX, pImageActorX);
	initImageActor(Coronal, center, pImageCast, pImageResliceY, pImageActorY);
	initImageActor(Sagittal, center, pImageCast, pImageResliceZ, pImageActorZ);

	vtkSmartPointer<vtkRenderer> pRendererX = vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderer> pRendererY = vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderer> pRendererZ = vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderer> pRenderer = vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderWindow> pRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();

	pRendererX->AddActor(pImageActorX);
	pRendererY->AddActor(pImageActorY);
	pRendererZ->AddActor(pImageActorZ);

	// 设置渲染器背景颜色
	pRendererX->SetBackground(0, 0, 0);
	pRendererY->SetBackground(0, 0, 0);
	pRendererZ->SetBackground(0, 0, 0);
	pRenderer->SetBackground(0.1, 0.2, 0.4);

	// 为每个渲染器设置视口
	double ltView[4] = { 0, 0, 0.5, 0.5 };
	double rtView[4] = { 0.5, 0, 1, 0.5 };
	double lbView[4] = { 0, 0.5, 0.5, 1 };
	double rbView[4] = { 0.5, 0.5, 1, 1 };

	pRenderer->SetViewport(rtView);
	pRendererX->SetViewport(lbView);
	pRendererY->SetViewport(rbView);
	pRendererZ->SetViewport(ltView);

	pRenderWindow->AddRenderer(pRendererX);
	pRenderWindow->AddRenderer(pRendererY);
	pRenderWindow->AddRenderer(pRendererZ);
	pRenderWindow->AddRenderer(pRenderer);

	// 设置体积渲染
	vtkSmartPointer<vtkPiecewiseFunction> volumeScalarOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
	volumeScalarOpacity->AddPoint(0, 0.0);
	volumeScalarOpacity->AddPoint(80, 0.0);
	volumeScalarOpacity->AddPoint(400, 1.0);

	vtkSmartPointer<vtkColorTransferFunction> volumeColor = vtkSmartPointer<vtkColorTransferFunction>::New();
	volumeColor->AddRGBPoint(0.0, 0.0, 0.0, 0.0);
	volumeColor->AddRGBPoint(80.0, 1.0, 1.0, 1.0);
	volumeColor->AddRGBPoint(400.0, 1.0, 1.0, 1.0);

	vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
	volumeProperty->SetColor(volumeColor);
	volumeProperty->SetScalarOpacity(volumeScalarOpacity);
	volumeProperty->ShadeOn();
	volumeProperty->SetInterpolationTypeToLinear();

	vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
	volumeMapper->SetInputConnection(reader->GetOutputPort());

	vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	pRenderer->AddVolume(volume);

	vtkSmartPointer<vtkRenderWindowInteractor> pRenderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	pRenderWindow->SetInteractor(pRenderWindowInteractor);

	pRenderWindow->SetSize(800, 800);

	// 为横断面视窗添加交互回调
	vtkSmartPointer<vtkRenderWindowInteractor> interactorX = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactorX->SetRenderWindow(pRenderWindow);
	addImageInteractionCallback(interactorX, pImageResliceX);

	vtkSmartPointer<vtkRenderWindowInteractor> interactorY = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactorY->SetRenderWindow(pRenderWindow);
	addImageInteractionCallback(interactorY, pImageResliceY);

	vtkSmartPointer<vtkRenderWindowInteractor> interactorZ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactorZ->SetRenderWindow(pRenderWindow);
	addImageInteractionCallback(interactorZ, pImageResliceZ);

	// 为体绘制窗口添加交互回调
	vtkSmartPointer<vtkRenderWindowInteractor> interactorVolume = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactorVolume->SetRenderWindow(pRenderWindow);

	vtkSmartPointer<vtkInteractorStyleTrackballCamera> volumeStyle = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
	interactorVolume->SetInteractorStyle(volumeStyle);

	pRenderWindow->Render();
	pRenderWindowInteractor->Initialize();
	pRenderWindowInteractor->Start();

	return 0;
}

运行效果:

待后期进行优化和完善。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/719921.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Fiddler实现重定向

fiddler设置响应后断点 命令&#xff1a;bpafter url 配置以后&#xff0c;此时服务器响应的数据在fiddler中被劫持&#xff0c;浏览器显示的是一片空白&#xff08;类似加载不出的效果&#xff09; fiddler中可以修改返回的响应内容 选择一个图片&#xff0c;然后点击run t…

6.S081——CPU调度部分(Xv6中的进程的状态转换)——xv6源码完全解析系列(11)

0.briefly speaking 时隔9个月&#xff0c;我又回来继续更新Xv6内核源码相关的内容了&#xff0c;上次更新之后经历了3个月的秋招&#xff0c;之后紧接着是实验室的中期检查&#xff0c;之后又是遥遥无期的毕业论文写作和修改&#xff0c;总算到现在有了一些自己的时间来继续做…

三分钟了解链动3+1模式

在电商领域的营销策略中&#xff0c;链动31模式以其独特的魅力和优势&#xff0c;吸引了众多商家的目光。下面&#xff0c;我们将对这一模式进行深度剖析&#xff0c;并探讨其相较于链动21模式的优势所在。 一、身份设置与奖励机制 链动31模式在身份设置上分为三种&#xff1…

历年各地区养老金发放人数,多图可用,含shp和excel格式

基本信息. 数据名称: 历年各地区养老金发放人数 数据格式: Shpexcel 数据几何类型: 面 数据坐标系: WGS84 数据时间&#xff1a;2012-2021年 数据来源&#xff1a;网络公开数据 数据可视化.

Python深度学习基于Tensorflow(17)基于Transformer的图像处理实例VIT和Swin-T

文章目录 VIT 模型搭建Swin-T 模型搭建参考 这里使用 VIT 和 Swin-T 在数据集 cifar10 上进行训练 VIT 模型搭建 导入需要的外部库 import numpy as np import tensorflow as tf import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec这里我们接着使用 ci…

华为手环9省电设置

1、 手环开启熄屏显示续航约3天&#xff0c;原因为屏幕持续常亮显示&#xff1b;如不需要可通过手环“设置->表盘->熄屏显示”路径进行关闭&#xff1b; 2、 手环具备后台健康自动检测功能&#xff0c;您可根据需要选择是否使用或关闭&#xff1a; &#xff08;1&#x…

使用Python进行并发和并行编程:提高效率的秘诀

使用Python进行并发和并行编程&#xff1a;提高效率的秘诀 ​ 大家好&#xff0c;今天我们来聊聊如何使用Python进行并发和并行编程&#xff0c;以提升数据处理的效率&#xff1b;在之前的文章中&#xff0c;我们探讨了Python的函数式编程和数据流处理。今天&#xff0c;我们将…

SGPT论文阅读笔记

这是篇想要用GPT来提取sentence embedding的工作&#xff0c;提出了两个框架&#xff0c;一个是SGPT-BE&#xff0c;一个是SGPT-CE&#xff0c;分别代表了Bi-Encoder setting和Cross-Encoder setting。CE的意思是在做阅读理解任务时&#xff0c;document和query是一起送进去&am…

【启明智显产品介绍】Model4 工业级HMI芯片详解系列专题(二):高清解码

Model4 工业级HMI芯片详解系列专题&#xff08;二&#xff09;【高清解码】 Model4 工业级HMI芯片集成了图形显示和编解码相关的硬件模块&#xff0c;为高清图像显示、高清视频播放和高清摄像头输入提供了强大的硬件基础&#xff1a; DE 显示引擎&#xff1a; 1 个 UI 图层&…

Unity引擎UGUI上特效处理重叠和裁剪问题的多种解决办法

大家好&#xff0c;我是阿赵。   使用Unity引擎开发项目&#xff0c;使用UGUI做界面&#xff0c;经常会遇到需要把特效放在UI上&#xff0c;但UI本身和特效又需要有遮挡关系和裁剪效果。   之前我介绍了一下使用MaskableGraphic的方式把粒子特效渲染在UI上&#xff0c;把粒…

电手出软件啦!各种姿势一键重装你的系统

电手的兄弟们你们好啊&#xff0c;很多兄弟都知道&#xff0c;我们老大傲梅是做软件的&#xff0c;例如大伙儿都用过的傲梅分区助手&#xff0c;还有傲梅轻松备份。相信不少兄弟都是用了分区助手才关注到电手的。 而我们电手&#xff0c;在电脑和手机玩机内容方面一直深耕。 跟…

【车载音视频AI电脑】全国产海事船载视频监控系统解决方案

海事船载视频监控系统解决方案针对我国快速发展的内河航运、沿海航运和远洋航运中存在的航行安全和航运监管难题&#xff0c;为船舶运营方、政府监管部门提供一套集视频采集、存储、回放调阅为一体的视频监控系统&#xff0c;对中大型船舶运行中的内部重要部位情况和外部环境进…

实现锚点链接点击tab跳转到指定位置 并且滚动鼠标顶部锚点的样式也跟随变化

实现效果如下 不管是点击还是 滚动鼠标 顶部的样式也会跟随变化 点击会跳转到指定的位置 通过IntersectionObserver 监听是否可见 下面代码可以直接执行到vue的文件 <template><div><ul class"nav"><li v-for"tab in tabs" :key…

京东和天猫各渠道区别是什么?你了解吗?如何快速了解两个平台渠道推广

1.快车/直通车区别: 京东:不能投竞品词,能投定向商品选竞品,因为京东是卖平台流量和商品(自营(主收入)),不可以投竞品词是为了保护自己店铺的品牌流量; 天猫:只卖平台流量,不卖商品,所以允许竞品词投放; 2.竞品人群圈选: 因为数坊是自身品牌数据分析平台,所…

php配合fiddler批量下载淘宝天猫商品数据分享

有个做电商的朋友问我&#xff0c;每次上款&#xff0c;需要手动去某宝去搬运商品图片视频&#xff0c;问我能不能帮忙写个脚本&#xff0c;朋友开口了&#xff0c;那就尝试一下 首先打开某宝&#xff0c;访问一款商品&#xff0c;找出他的数据来源 通过观察我们发现主图数据来…

C# 与三菱PLC MC协议通讯

1. 引用HslCommunication Nuget包里边添加 HslCommunication包的引用 2.创建PLC连接对象&#xff0c;并通过 IP&#xff0c;端口进行连接 //PLC连接对象 var plc new MelsecMcNet(_ip, _port); plc.ConnectTimeOut 3000;var res plc.ConnectServer();//连接PLCisConnect …

苹果Mac电脑遭恶意软件攻击 Mac第三方恶意软件删除不了

苹果Mac电脑一直以来都以安全性和稳定性著称&#xff0c;许多用户认为Mac电脑不会受到恶意软件的侵害&#xff0c;但事实上&#xff0c;Mac电脑也不是绝对安全的&#xff0c;近年来&#xff0c;有越来越多的恶意软件针对Mac电脑进行攻击&#xff0c;甚至有些恶意软件可以绕过苹…

镭速是如何做到传输中快速校验大文件的

在信息泛滥的当下&#xff0c;文件传输系统的效率与安全性成为企业和个人用户高度关注的焦点。传统上&#xff0c;文件传输依赖于如MD5或XXHash等单一的完整性校验机制。 然而&#xff0c;在多变的工作环境中&#xff0c;这些传统方法显得不够灵活。镭速&#xff0c;作为大文件…

文库小程序搭建部署:实现资源共享正向反馈

文档库相信大家应该不陌生&#xff0c;日常我们的工作模板、会议模板、求职时的简历模板、教育界的教学模板等来源方式都出自于文档库&#xff0c;随着互联网的发展和工作需求&#xff0c;文档模板开启了新型的知识变现新途径&#xff0c;通过文库小程序&#xff0c;我们不仅能…

9.2.2 DeepLab系列模型中每一代的创新是什么?是为了解决什么问题?

9.2.2 DeepLab系列模型中每一代的创新是什么&#xff1f;是为了解决什么问题&#xff1f; 前情回顾&#xff1a;9.2.1 简述图像分割中经常用到的编码器-解码器网络结构的设计理念。 DeepLab是Google 团队提出的一系列图像分割算法。 DeepLab v1在2014年被提出&#xff0c;并在…