VTK随笔六:VTK图像处理(图像创建、图像显示)

news2024/9/23 3:29:53

一、VTK图像创建

1、VTK 图像数据结构

         数字图像文件内容由两个部分组成:图像头信息和数据。图像头信息定义了图像的基本信息,主要包括起点位置(Origin)、像素间隔(Space)和维数(Dimension)。通过这三个参数即可确定图像空间位置和大小。

        图像数据即为图像像素的像素值,一般采用一维数组来表示和存储。 

2、VTK 图像创建

 1)图像源 Source
        VTK 中内置了多个创建图像的Source类,利用这些Source 类可以快速创建图像。以 vtkImageCanvasSource2D为例。该Source 类的功能是创建一个画布(空白图像),并提供了多种几何图形(点、线段、圆、矩形以及图像等)的绘制填充功能。 

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkGenericOpenGLRenderWindow.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkImageCanvasSource2D> canvas = vtkSmartPointer<vtkImageCanvasSource2D>::New();
    canvas->SetScalarTypeToUnsignedChar();
    canvas->SetNumberOfScalarComponents(1);
    canvas->SetExtent(0, 100, 0, 100, 0, 0);
    canvas->SetDrawColor(0, 0, 0, 0);
    canvas->FillBox(0,100,0,100);
    canvas->SetDrawColor(255, 0, 0, 0);
    canvas->FillBox(20,40,20,40);
    canvas->Update();

    // Create actors
    vtkSmartPointer<vtkImageActor> redActor = vtkSmartPointer<vtkImageActor>::New();
    redActor->SetInputData(canvas->GetOutput());

    // Setup renderers
    vtkSmartPointer<vtkRenderer> redRenderer = vtkSmartPointer<vtkRenderer>::New();
    redRenderer->AddActor(redActor);
    redRenderer->ResetCamera();
    redRenderer->SetBackground(1.0, 1.0, 1.0);

    // Setup render window
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(redRenderer);
    QVTKOpenGLNativeWidget w;
    w.setWindowTitle("ImageCanvasSource2D");
    w.setRenderWindow(renderWindow);
    w.show();

    return a.exec();
}

 运行效果:

        除了 vkImageCanvasSource2D外,VTK还提供了其他类似的Source 类来快速生成特定的图像,例如 vtkImageEllipsoidSource,该类根据指定的中心以及各个轴的半径来生成一个前景为椭圆(球)的二值图像;vtkImageGaussianSource 类生成一幅像素值服从高斯分布的图像;vtkImageGridSource用于生成网格线图像;vtkImageNoiseSource 生成一个像素值为随机数的噪声图像;vtkImageSinusoidSource生成的图像像素值由正弦函数决定 。

2) 直接创建图像

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkInformation.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkGenericOpenGLRenderWindow.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkImageData> img =  vtkSmartPointer<vtkImageData>::New();
    vtkSmartPointer<vtkInformation> info =  vtkSmartPointer<vtkInformation>::New();
    img->SetDimensions(16,16,1);
    img->SetScalarType(VTK_UNSIGNED_CHAR,info);
    img->SetNumberOfScalarComponents(1,info);
    img->AllocateScalars(info);

    unsigned char *ptr = (unsigned char*)img->GetScalarPointer();
    for(int i=0; i<16*16*1; i++)
    {
        *ptr ++ =i%256;
    }

    vtkSmartPointer<vtkImageActor> redActor = vtkSmartPointer<vtkImageActor>::New();
    redActor->SetInputData(img);

    vtkSmartPointer<vtkRenderer> redRenderer = vtkSmartPointer<vtkRenderer>::New();
    redRenderer->AddActor(redActor);
    redRenderer->ResetCamera();
    redRenderer->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(redRenderer);
    QVTKOpenGLNativeWidget w;
    w.setWindowTitle("CreateVTKImageData");
    w.setRenderWindow(renderWindow);
    w.show();

    return a.exec();
}

        首先定义vtklmageData指针,然后指定图像的维数,而图像的原点和像素间隔则都是采用默认值,因此不需要设置。SetScalarType指定图像的每个像素值的数据类型为unsigned char,SetNumberOfScalarComponents则指定了每个像素值的数据成分为1,每个像素值为1个标量值,参数设置完毕后,调用AllocateScalars()分配内存,生成图像数据。图像生成后,默认所有像素值为0。可以通过访问图像数据数组来设每个像素值GetScalarPointer()即返回图像的数据数组(图像数据数组都采用一维数组),然后根据图像的大小,访问每个像素并为其赋值。生成的图像如下所示:

二、VTK图像显示

 1、vtklmageViewer2

        vtklmageViewer2 中封装了 VTK 图像显示的可视化渲染引擎,包括 vtkActor、vtkRender、vtkRenderWindow、vtkInteractorStypelmage等对象,可以方便地完成图像显示和交互。该类提供的主要交互操作有图像放缩、窗宽窗位调节,并提供切片选择及切片方向设置接口,尤其适合三维图像的切片显示。

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkMetaImageReader.h>
#include <vtkImageViewer2.h>
#include <vtkRenderer.h>
#include <QVTKOpenGLNativeWidget.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkMetaImageReader> reader = vtkSmartPointer<vtkMetaImageReader>::New();
    reader->SetFileName("D:/data/brain.mhd");
    reader->Update();

    vtkSmartPointer<vtkImageViewer2> imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
    imageViewer->SetInputConnection(reader->GetOutputPort());
    imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);

    QVTKOpenGLNativeWidget w;
    imageViewer->SetupInteractor(w.interactor()); //初始化交互器
    imageViewer->SetRenderWindow(w.renderWindow());  //初始化渲染窗口
    w.setWindowTitle("DisplayImageExample");
    w.show();
    imageViewer->SetColorLevel(500); //窗位
    imageViewer->SetColorWindow(2000); //窗宽
    imageViewer->SetSlice(40); //切片索引
    imageViewer->SetSliceOrientationToXY(); //切片方向

    return a.exec();
}

vtklmageViewer2显示三维图像的某个切片:

 1)窗宽/窗位的概念
        窗宽是图像显示的灰度范围。一般显示器的灰度范围为256级,而医学图像的灰度范围则远远大于该范围,因此通过显示器显示时不能显示所有灰度级,需要使用窗宽来定义欲显示的灰度范围。当灰度值高于该范围的最大值时,均以白影显示;当低于该范围时,均以黑色显示。若增大窗宽,则显示具有不同灰度值的组织结构增多,但是会降低组织之间的对比度,若减小窗宽,则可视的不同灰度组织结构会减少,同时增大组织结构的对比度。

2)医学图像二维视图
        切片(Slice)或切面是三维图像比较常用的概念,尤其在医学图像中,不同方向的切面都有特定的名字,分别是:矢状面(SagitalPlane),沿着身体前后径所做的与地面垂直的切面;冠状面(CoronalPlane),沿着身体左右径所做的与地面垂直的切面;横断面(Transverse/AxialPlane),是指横断身体与地面平行的切面。

 2、vtklmageActor

vtkImageActor 是一个三维图像渲染 Actor,通过纹理映射将图像映射到一个多边形上进行显示。 

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkBMPReader.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
    reader->SetFileName ("D:/data/lena.bmp");
    reader->Update();

    vtkSmartPointer<vtkImageActor> imgActor =vtkSmartPointer<vtkImageActor>::New();
    imgActor->SetInputData(reader->GetOutput());

    vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(imgActor);
    renderer->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("DisplayImageExample");
    w.show();

    return a.exec();
}

运行效果:

        需要注意的是,vtkImageActor 接收的图像数据 vtkImageData像素类型必须为unsigned char,如果类型不符合要求,在显示图像前需要先将图像数据类型转换为unsigned char。 

3、图像融合 

        图像融合是利用图像的不透明度来合成图像。在 VTK 中,用类 vtkImageBlend 实现图像的融合。 vtkmageBlend 可以接收多个图像输入,其输出为融合图像。输出图像的像素间隔、原点、范围以及像素组分个数与第一个图像一致。

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageBlend.h>
#include <vtkRenderer.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
    reader->SetFileName ("D:/data/lena-gray.jpg");
    reader->Update();

    vtkSmartPointer<vtkImageCanvasSource2D> imageSource = vtkSmartPointer<vtkImageCanvasSource2D>::New();
    imageSource->SetNumberOfScalarComponents(1);
    imageSource->SetScalarTypeToUnsignedChar();
    imageSource->SetExtent(0, 512, 0, 512, 0, 0);
    imageSource->SetDrawColor(0.0);
    imageSource->FillBox(0, 512, 0, 512);
    imageSource->SetDrawColor(255.0);
    imageSource->FillBox(100,400,100,400);
    imageSource->Update();

    vtkSmartPointer<vtkImageBlend> imageBlend = vtkSmartPointer<vtkImageBlend>::New();
    imageBlend->AddInputData(reader->GetOutput());
    imageBlend->AddInputData(imageSource->GetOutput());
    imageBlend->SetOpacity(0, 0.4);
    imageBlend->SetOpacity(1, 0.6);
    imageBlend->Update();

    // Create actors
    vtkSmartPointer<vtkImageActor> originalActor1 = vtkSmartPointer<vtkImageActor>::New();
    originalActor1->SetInputData(reader->GetOutput());

    vtkSmartPointer<vtkImageActor> originalActor2 =vtkSmartPointer<vtkImageActor>::New();
    originalActor2->SetInputData(imageSource->GetOutput());

    vtkSmartPointer<vtkImageActor> blendActor = vtkSmartPointer<vtkImageActor>::New();
    blendActor->SetInputData(imageBlend->GetOutput());

    // Define viewport ranges (xmin, ymin, xmax, ymax)
    double leftViewport[4] = {0.0, 0.0, 0.33, 1.0};
    double midViewport[4] = {0.33, 0.0, 0.66, 1.0};
    double rightViewport[4] = {0.66, 0.0, 1.0, 1.0};

    // Setup renderers
    vtkSmartPointer<vtkRenderer> originalRenderer1 = vtkSmartPointer<vtkRenderer>::New();
    originalRenderer1->AddActor(originalActor1);
    originalRenderer1->ResetCamera();
    originalRenderer1->SetBackground(1.0, 1.0, 1.0);
    originalRenderer1->SetViewport(leftViewport);

    vtkSmartPointer<vtkRenderer> originalRenderer2 = vtkSmartPointer<vtkRenderer>::New();
    originalRenderer2->AddActor(originalActor2);
    originalRenderer2->ResetCamera();
    originalRenderer2->SetBackground(1.0, 1.0, 1.0);
    originalRenderer2->SetViewport(midViewport);

    vtkSmartPointer<vtkRenderer> blendRenderer = vtkSmartPointer<vtkRenderer>::New();
    blendRenderer->AddActor(blendActor);
    blendRenderer->ResetCamera();
    blendRenderer->SetBackground(1.0, 1.0, 1.0);
    blendRenderer->SetViewport(rightViewport);

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(originalRenderer1);
    renderWindow->AddRenderer(originalRenderer2);
    renderWindow->AddRenderer(blendRenderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640,320);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("ImageBlendExample");
    w.show();

    return a.exec();
}

 运行效果:

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

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

相关文章

续航更进阶 长安马自达MAZDA EZ-6成功挑战1301公里续航

继在中国“热极”新疆吐鲁番完成高温试炼后&#xff0c;8月24日-26日&#xff0c;长安马自达MAZDA EZ-6&#xff08;以下称EZ-6&#xff09;“众测先享官—续航更进阶”再次从兰州出发&#xff0c;EZ-6增程车型以一次充电、一箱油&#xff08;45L油箱&#xff09;创造了CLTC工况…

微信小程序主体变更(迁移)法人无法配合扫脸怎么办?

小程序主体变更是指公众平台提供的&#xff0c;协助小程序帐号开发者将其小程序项下业务交由其他开发者的小程序承接、运营的功能和服务。主体变更完成后&#xff0c;小程序的运营权限、主体信息将发生变化。 那么&#xff0c;小程序怎么变更主体信息呢&#xff1f;法人因种种…

游戏开发设计模式之原型模式

目录 原型模式的实现步骤 原型模式的优点 原型模式的应用场景 总结 原型模式在游戏开发中的具体应用案例是什么&#xff1f; 如何在不同编程语言中实现原型模式&#xff1f; Java C# Python C JavaScript 原型模式与其他创建型设计模式&#xff08;如建造者模式、适…

喂饭级教程!零代码搭建本地个人知识库 ,支持GPT4、Llama3、Kimi等十几种大模型

这篇文章是关于搭建本地个人知识库&#xff0c;零代码&#xff01;喂饭级教程&#xff01;支持GPT、Llama3、Kimi等十几种大模型。教程由我编写&#xff0c;每一步已经过验证&#xff0c;可实践&#xff01; 1 搭建本地知识库优势 部署本地知识库&#xff0c;可以借助大模型能…

国内十大企业薪酬管理咨询公司

思博咨询专注于制造业管理咨询落地辅导。提供战略落地、营销体系、组织体系、薪酬绩效、供应链、精益生产、降本增效、工厂规划等管理咨询服务。 在当今这个竞争激烈的市场环境中&#xff0c;企业薪酬管理已不再是简单的工资发放与调整&#xff0c;而是成为了企业战略的重要组成…

大模型学习成长路径:五个阶段晋级指南,你在哪一级?

第一阶段 不知道概念 第一阶段&#xff0c;「不知道大模型是什么意思」&#xff0c;不知道langchain是什么&#xff0c;不知道llm是什么&#xff0c;不知道文心一言&#xff0c;不知道openAI&#xff0c;不知道prompt是什么&#xff1f; 这个阶段就是疯狂百度&#xff0c;像一…

23 预编译详解

目录 一、预定义符号 二、#define定义常量 三、#define定义宏 四、带有副作用的宏参数 五、宏替换的规则 六、宏函数的对比 七、#和## &#xff08;一&#xff09;#运算符 &#xff08;二&#xff09;##运算符 八、命名约定 九、#undef 十、命令行定义 十一、条件编…

TCP协议中的可靠性机制

目录 确认应答 滑动窗口 快重传 流量控制 窗口探测 拥塞控制 延迟应答 捎带应答 总结 相较于UDP协议&#xff0c;TCP协议由于要确保通信过程中的可靠性与尽可能提高通信效率提供了很多可靠性机制&#xff0c;因此TCP比较复杂。 确认应答 滑动窗口 滑动窗口是发送方/接…

Jmeter执行多机联合负载

1、注意事项&#xff0c;负载机必须要安装jre&#xff0c;控制机则必须安装jdk。要配置同网段ip&#xff0c;双向关闭防火墙。 每个负载机要平均承担线程数。 具体执行事项查看上面截图所示&#xff0c;控制机和负载机配置。 2、先给负载机设置ip地址&#xff0c;保持与控制…

网络安全新视角:人工智能在防御中的最新应用

人工智能在网络安全中的最新应用 概述 人工智能&#xff08;AI&#xff09;在网络安全领域的应用正日益成熟&#xff0c;它通过机器学习和深度学习技术&#xff0c;为网络安全带来了革命性的变革。AI技术不仅能够自动化、智能化地检测、分析和应对安全威胁&#xff0c;还能够…

Transformer-BiLSTM神经网络多输入单输出回归预测的MATLAB实现

在现代人工智能和机器学习领域&#xff0c;深度学习模型已经成为解决复杂问题的重要工具。Transformer和双向长短期记忆网络&#xff08;BiLSTM&#xff09;是两种非常强大的神经网络架构&#xff0c;它们在自然语言处理、时间序列预测、图像处理等多个领域表现出色。本文将介绍…

黑马JavaWeb企业级开发(知识清单)07——Ajax、Axios请求、前后端分离开发介绍、Yapi配置步骤

文章目录 前言一、Ajax1. 概述2. 作用3. 同步异步4. 原生Ajax请求&#xff08;了解即可&#xff09;5. Axios&#xff08;重点&#xff09;5.1 基本使用5.2 Axios别名&#xff08;简化书写&#xff09; 二、前后端分离开发1. 介绍1.1 前后台混合开发1.2 前后台分离开发方式&…

ChatGPT真的那么牛吗?

ChatGPT 很受欢迎&#xff0c;主要因为它在很多任务上表现出色&#xff0c;比如回答问题、写作、编程辅助等等。它的强大之处在于它可以理解和生成与上下文相关的自然语言文本&#xff0c;使得它在许多领域中都有用武之地。 和咱国内的文心一言一比较比较就知道了 不抖机灵&…

史上最全软件测试面试题集(含答案),进大厂涨薪必备,赶紧收藏

前阵子一位读者告诉我&#xff0c;某位大厂HR给他发了我之前做的面试题答案合集。 这个消息让我开心了一整天&#xff0c;因为这说明我之前做的面试题系列真的能帮助到部分测试同学&#xff0c;也算是侧面得到了一种认可吧。 今天写的这份面试题我之前就整理分享过&#xff0…

HTB-Explosion(rdp连接)和preignition(目录遍历)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解Explosion靶机 - Explosion 渗透过程 信息搜集 发现服务器开起了3389端口远程服务 远程连接rdp服务 xfreerdp /v:10.129.172.157 /u:Administrator /p: /v 主机名 /u 用户名 /p密码 这篇靶机是对rdp服…

问题记录:树莓派3B+安装OpenMediaVault(OMV)后无WiFi连接处理

目录 实验环境参考教程安装前直接避免出现该问题的方法问题&#xff1a;安装完OpenMediaVault后&#xff0c;此前已配置好的WiFi&#xff0c;无法正常连接解决方法 OpenMediaVault 登录 实验环境 时间&#xff1a;2024年08月27日 硬件&#xff1a;树莓派3B 系统&#xff1a;Ra…

代码随想录算法训练营第三十九天| 图论理论基础

今天是图论入门的第一天&#xff0c;主要的学习内容主要是图论的理论基础。 图论理论基础 图的种类 图一般可以分为有向图和无向图&#xff0c;无向图是指边没有方向&#xff0c;有向图是指边有方向&#xff0c;其中&#xff0c;还存在一种加权有向图&#xff0c;指的是每条…

ATR - LSIs supported BIT

6.3.3 Global Interface bytes ts_102221v170400p.pdf

【人工智能】多模态AI:如何通过融合文本、图像与音频重塑智能系统未来

我的主页&#xff1a;2的n次方_ ​ 随着人工智能技术的飞速发展&#xff0c;多模态AI逐渐成为构建智能系统的重要方向。传统的AI系统通常依赖于单一模态的数据&#xff0c;如文本、图像或音频。而多模态AI通过结合多种数据类型&#xff0c;能够在更复杂的场景下提供更智能的解…

给自己复盘的随想录笔记-链表

链表 定义 数字域和指针域 种类 单链表&#xff0c;双链表&#xff0c;循环链表 链表的存储方式 链表是通过指针域的指针链接在内存中各个节点。 所以链表中的节点在内存中不是连续分布的 &#xff0c;而是散乱分布在内存中的某地址上&#xff0c;分配机制取决于操作系统…