基于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;
}

运行效果:

待后期进行优化和完善。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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

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

Web服务器与Apache(LAMP架构+搭建论坛)

一、Web基础 1.HTML概述 HTML&#xff08;Hypertext Markup Language&#xff09;是一种标记语音,用于创建和组织Web页面的结构和内容&#xff0c;HTML是构建Web页面的基础&#xff0c;定义了页面的结构和内容&#xff0c;通过标记和元素来实现 2.HTML文件结构 <html>…

压缩pdf文件大小在线,在线免费压缩pdf

在现在办公中&#xff0c;PDF文档已经成为我们日常工作中不可或缺的一部分。然而&#xff0c;随着文档内容的不断丰富&#xff0c;PDF文件的大小也逐渐增大&#xff0c;这不仅占用了大量的存储空间&#xff0c;而且在传输和共享时也显得尤为不便。所以有时候我们需要把pdf压缩小…

# Kafka_深入探秘者(4):kafka 主题 topic

Kafka_深入探秘者&#xff08;4&#xff09;&#xff1a;kafka 主题 topic 一、kafka 主题管理 1、kafka 创建主题 topic 命令 1&#xff09;命令&#xff1a; # 切换到 kafka 安装目录 cd /usr/local/kafka/kafka_2.12-2.8.0/# 创建一个名为 heima 的 主题 bin/kafka-topic…

揭秘!速卖通卖家如何靠自养号测评打造爆款?

然而&#xff0c;许多商家对测评的认识存在严重的误区&#xff0c;他们错误地以为仅仅通过几次草率的测评就能快速塑造出爆款产品。实际上&#xff0c;测评远非如此简单&#xff0c;它是一个需要深思熟虑、精心策划和持续投入的过程。测评的真正价值在于帮助平台精准地把握产品…

Java-LinkedList和ArrayList的区别、Get/Add操作性能分析以及常见的遍历方式

LinkedList和ArrayList的区别、Get/Add操作性能分析以及常见的遍历方式 一、LinkedList基本特性主要方法 二、ArrayList初始化及基本操作ArrayList注意点&#xff08;待完善&#xff09;代码示例 三、ArrayList与LinkedList的区别四、Get/Add操作性能分析五、LinkedList遍历方式…

中霖教育:二级建造师报名后缺考有影响吗?

在完成二级建造师的报名程序后&#xff0c;考生无法进行退考。如果是不参加考试&#xff0c;可以选择弃考。弃考对个人并没有负面影响&#xff0c;缺席考试的话也不会被记录在个人诚信档案中。当然&#xff0c;如果弃考的话此次考试的成绩将被记为0&#xff0c;下一年参加考试按…

关于电机的线性思考

当大多数工程师听到电机这个词时&#xff0c;他们自然地想到旋转装置&#xff0c;例如有刷直流、无刷直流、步进电机或变频原动机。但是电机不一定是旋转的&#xff0c;很多时候设计需要直线运动。一种解决方案是添加某种齿轮或皮带装置来转换旋转运动&#xff0c;这种解决方案…

基于SpringBoot的实习管理系统设计与实现

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; SpringBoot框架&#xff0c;B/S模式 工具&#xff1a; MyEclipse&#xff0c;Tomcat 系统展示 …

预备役二招算法测试题解

这次题目出的都是一些偏向于基础的题目&#xff0c;就是一些简单的模拟&#xff0c;思维&#xff0c;以及基础算法&#xff08;二分&#xff0c;前缀和&#xff09; &#xff08;点击题目标题&#xff0c;进入原题&#xff09; 我是签到题 题解&#xff1a;就是说给你 t 组数据…

每日鲜语携手中国国家高尔夫球队队员殷若宁征战巴黎,打响中国高端鲜奶品牌“鲜”声量

近日&#xff0c;高端鲜奶品牌每日鲜语宣布携手蒙牛品牌代言人、中国国家高尔夫球队队员殷若宁&#xff0c;共赴巴黎奥运赛场&#xff0c;为梦想挥杆而上。邀请众多消费者开启高品质、健康的生活方式。此举不仅彰显了每日鲜语作为高端鲜奶新标杆的品牌定位&#xff0c;也同时延…

vue2.0项目安装依赖 sass 报错

1、报错代码&#xff1a; 2、原因&#xff1a;项目有点老&#xff0c;vue2的版本&#xff0c;所以node-sass在npm安装的时候大概率的会安装出错&#xff0c;或下载时间过长&#xff0c;因此考虑用dart-sass来替换。 npm install node-sassnpm:dart-sass3、然后就可以成功运行了…

8.项目结构——黑马程序员Java最新AI+若依框架项目

目录 前言一、后端1.ruoyi-admin2.ruoyi-common3.ruoyi-framework4. ruoyi-generator(可删除)5.ruoyi-quartz&#xff08;可删除&#xff09;5.ruoyi-system6. ruoyi-ui7.sql8.依赖关系9. 总结 二、前端三、SQL 前言 提示&#xff1a;本篇叙述若依前后端项目结构 一、后端 1…

无线领夹麦克风哪个品牌音质最好,揭秘无线麦克风哪个牌子最好!

​在这个数字化、信息化的时代&#xff0c;短视频和直播已经成为了人们生活中不可或缺的一部分。而无线麦克风&#xff0c;则是这些活动中不可或缺的重要工具。它们能够轻松捕捉声音&#xff0c;让内容更加生动、真实。然而&#xff0c;市场上的无线麦克风种类繁多&#xff0c;…

51-60 CVPR 2024 最佳论文 | Generative Image Dynamics

在2023年11月&#xff0c;谷歌研究院发布了一项令人瞩目的研究成果——Generative Image Dynamics&#xff08;生成图像动力学&#xff09;。这项技术的核心是将静态的图片转化为动态的、无缝循环的视频&#xff0c;而且更令人兴奋的是&#xff0c;这些生成的视频还具有交互性。…

AI赋能天气:微软研究院发布首个大规模大气基础模型Aurora

编者按&#xff1a;气候变化日益加剧&#xff0c;高温、洪水、干旱&#xff0c;频率和强度不断增加的全球极端天气给整个人类社会都带来了难以估计的影响。这给现有的天气预测模型提出了更高的要求——这些模型要更准确地预测极端天气变化&#xff0c;为政府、企业和公众提供更…

【转】5种常见的网络钓鱼攻击以及防护手段

2022 年 Verizon 数据泄露调查报告指出&#xff0c;去年 75% 的社会工程攻击涉及网络钓鱼&#xff0c;仅去年一年就有超过 33 万个账户被网络钓鱼&#xff0c;网络钓鱼占整体社会工程攻击的 41%。 不能将所有责任归咎于员工&#xff0c;因为薄弱的安全意识建设及宣教是大部分漏…

XSS跨站攻击漏洞

XSS跨站攻击漏洞 一 概述 1 XSS概述 xss全称为&#xff1a;Cross Site Scripting&#xff0c;指跨站攻击脚本&#xff0c;XSS漏洞发生在前端&#xff0c;攻击的是浏览器的解析引擎&#xff0c;XSS就是让攻击者的JavaScript代码在受害者的浏览器上执行。 XSS攻击者的目的就是…

Windows 中 Chrome / Edge / Firefox 浏览器书签文件默认存储路径

1. Chrome 浏览器 按组合键 Win R&#xff0c;打开运行对话框&#xff0c;输入 %USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default或在Chrome 浏览器地址栏输入 chrome://version查看【个人资料路径】 2. Edge 浏览器 按组合键 Win R&#xff0c;打开运行对…

GD32F4xx 移植agile_modbus软件包与电能表通信

目录 1. agile_modbus1.1 简介1.2 下载2. agile_modbus使用2.1 源码目录2.2 移植3. 通信调试3.1 代码3.3 通信测试1. agile_modbus 1.1 简介 agile_modbus是一个轻量级的Modbus协议栈,主要特点: 支持RTU和TCP协议,采用纯C语言开发,不涉及任何硬件接口,可直接在任何形式的…