当前位置: 首页 > news >正文

VTK知识学习(26)- 图像基本操作(一)

1、前言

        图像处理离不开一些基本的图像数据操作,例如获取和修改图像的基本信息、访问和修改图像像素值、图像显示、图像类型转换等。熟练掌握这些基本操作有助于使用 VTK进行图像处理应用程序的快速开发。

2、图像信息的访问与修改

1)利用vtkIamgeData方法

        vtkImageData中提供了多个函数用于访问或者获取图像的基本信息,这些函数通常以 Set或者 Get加上相应的信息名的形式进行命名,例如获取图像维数的方法定义为 GetDimensions()。

private void TestGetImageInfo()
{vtkBMPReader reader = vtkBMPReader.New();reader.SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena.bmp");reader.Update();int[] dims = reader.GetOutput().GetDimensions();Console.WriteLine($"图像维数:{dims[0]} {dims[1]} {dims[2]}");double[] orgin = reader.GetOutput().GetOrigin();Console.WriteLine($"图像原点:{orgin[0]} {orgin[1]} {orgin[2]}");double[] spaceing = reader.GetOutput().GetSpacing();Console.WriteLine($"像素间隔:{spaceing[0]} {spaceing[1]} {spaceing[2]}");vtkImageActor actor = vtkImageActor.New();actor.SetInputData(reader.GetOutput());vtkRenderer renderer = vtkRenderer.New();renderer.AddActor(actor);renderer.ResetCamera();renderer.SetBackground(1, 1, 1);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(renderer);renderWindow.Render();
}

        示例主要获取了图像的三个信息,即图像维数、图像原点和像素间隔。

        VTK 中无论是二维图像还是三维图像,都用 vtkImageData表示,因此程序中定义图像维数为 dims[3],然后利用 GetDimensions()函数获取图像的维数;图像的原点和像素间隔都是物理空间数值,其数值类型为 double。从显示结果中可以看到,图像维数为512x512x1,其中Z方向的维数为1,说明该图像为二维图像:而图像的原点为(0,0,0)点,像素间隔为(1,1,1)。

2)利用类vtkChangeImageInformation

        vtkImageData 中提供了多个 Set 函数用于设置图像的基本信息。在对一个图像 Filter的输出图像信息进行修改后,如果 Filter 重新 Update,图像信息又会恢复回原来的值。而vtkChangeImageInformation 类可以作为管线中的一个 Filter 来修改图像信息。利用这个Filter 可以修改图像的原点、像素间隔以及范围,另外还可以实现图像平移缩放等操作。

private void TestChangeImageInfo()
{vtkBMPReader reader = vtkBMPReader.New();reader.SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena.bmp");reader.Update();int[] dims = reader.GetOutput().GetDimensions();Console.WriteLine($"原图像维数:{dims[0]} {dims[1]} {dims[2]}");double[] orgin = reader.GetOutput().GetOrigin();Console.WriteLine($"原图像原点:{orgin[0]} {orgin[1]} {orgin[2]}");double[] spaceing = reader.GetOutput().GetSpacing();Console.WriteLine($"原像素间隔:{spaceing[0]} {spaceing[1]} {spaceing[2]}");vtkImageChangeInformation changer = vtkImageChangeInformation.New();changer.SetInputData(reader.GetOutput());changer.SetOutputOrigin(100, 100, 0);changer.SetOutputSpacing(5, 5, 1);changer.SetCenterImage(1);changer.Update();dims = changer.GetOutput().GetDimensions();Console.WriteLine($"修改后图像维数:{dims[0]} {dims[1]} {dims[2]}");orgin = changer.GetOutput().GetOrigin();Console.WriteLine($"修改后图像原点:{orgin[0]} {orgin[1]} {orgin[2]}");spaceing = changer.GetOutput().GetSpacing();Console.WriteLine($"修改后像素间隔:{spaceing[0]} {spaceing[1]} {spaceing[2]}");vtkImageActor actor = vtkImageActor.New();actor.SetInputData(changer.GetOutput());vtkRenderer renderer = vtkRenderer.New();renderer.AddActor(actor);renderer.ResetCamera();renderer.SetBackground(1, 1, 1);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(renderer);renderWindow.Render();
}

        示例先读入图像,由 vtklmageData提供的函数接口获取图像的维数、图像原点和像素间隔。然后定义 vtkImageChangeInformation 对象,并设置输出图像原点为(100,100,0),输出图像像素间隔为(5,5,1),然后调用 CenterImage()函数将图像的原点置于图像的中心。
        操作后的结果使得图像的原点位于(-1277.5,-1275.5,0)。

        SetOutputOrigin(100,100,0)并没有起作用。查看 CenterImage()函数的注释,可以发现该函数的作用是将(0,0,0)点置于图像的中心。当Centerlmage()函数执行时会重新调用 SetOutputOrigin(),所以开始的 SetOutputOrigin()函数设置的原点将会被覆盖。

        (-1277.5,-1275.5,0)是如何计算出来的呢?

        根据图像的维数和像素间隔计算得到新的图像的宽度和高度为(512-1)x5,初始图像的原点位于(0,0,0),现在将图像的中心平移至原点,平移量为(-(512-1)x5/2,(512-1)x5/2,0)=(-1277.5,-1275.5,0)。

3、图像像素值的访问与修改

        图像像素值的访问与修改是最常用的一种操作。VTK 中提供了两种访问图像像素值的方法第一种方法是直接访问 vtkImageData 的数据数组,这种方法最直接。前面创建图像赋值时也是采用这种方法。vtkImageData中提供了GetScalarPointer()函数获取数据数组指针,该函数有三种形式:

virtual void *GetScalarPointer(int coordinates[3]);
virtual void *GetScalarPointer(int x, int y, int z);
virtual void *GetScalarPointer();

        前两种形式根据给定的像素索引得到指定的像素值,注意返回的是第(x,y,z)个像素值的地址。而第三种形式是返回图像数据数组的头指针,然后根据头指针可以依次访问索引像素。

1)数据数组

一个遍历图像像素的示例:

private void TestVisitPixel()
{vtkBMPReader reader = vtkBMPReader.New();reader.SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena.bmp");reader.Update();//获取图像的大小int[] dims = reader.GetOutput().GetDimensions();//将图像的100*100大小的区域设置为黑色for (int k = 0; k < dims[2]; k++){for (int j = 0; j < dims[1]; j++){for (int i = 0; i < dims[0]; i++){if (i < 100 && j < 100){//VTK彩色及矢量图像的像素存储格式示意: …R G B R G B…byte[] infos = new byte[] { 0, 0, 0 };var pixel = reader.GetOutput().GetScalarPointer(i, j, k);Marshal.Copy(infos, 0, pixel, 3);}}}}vtkImageActor actor = vtkImageActor.New();actor.SetInputData(reader.GetOutput());vtkRenderer renderer = vtkRenderer.New();renderer.AddActor(actor);renderer.ResetCamera();renderer.SetBackground(1, 1, 1);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(renderer);renderWindow.Render();
}

        实现了将图像的 100x100大小的区域设置为黑色。先定义一个 reader 读取一幅 BMP 图像,通过 vtkImageData的 GetDimensionsO)函数获取图像的大小。然后建立三重循环,通过 GetScalarPointer(i,j,k)函数获取访问图像像素值。

        需要注意的是,GetScalarPointer0函数返回的是 void*类型,因此需要根据图像的实际类型进行强制转换。如上面代码中将像素值数组的头指针类型转换为unsignedchar*。如果对数据类型不确定,还可以将图像数据类型强制转换为特定的数据类型,再进行遍历。

当然这个使用是指在c++中,在我们c#中你也看到是使用Marshal对指针进行复制操作了。

VTK 彩色以及矢量图像采用的是类似图 所示的像素存储格式。

        因此在修改 RGB 图像以及矢量图像像素时,需要根据像素的元组的组分数目来访问。例中,需要修改每个像素的 RGB 值时,先获得第(i,i,k)个像素的地址也就是R值的地址,然后将地址加1来访问后续G值以及B值。如果对于像素的元组组分不确定,可以通过函数GetNumberOfScalarComponents()来获取,代码如下所示:

int nbOfComp = reader->GetOutput()->GetNumberOfScalarComponents();
2)迭代器方法访问图像像素

        用 vtkImagelterator 类实现迭代器方法访问图像像素。该类是一个模板类使用时,需要提供迭代的图像像素类型以及迭代的区域大小。

        这个是c++的方式,c#没有找到对应的实现。

void TestVisitImagePixelIteratively(){vtkSmartPointer<vtkBMPReader> reader =vtkSmartPointer<vtkBMPReader>::New();reader->SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena.bmp");reader->Update();int numComponents = reader->GetOutput()->GetNumberOfScalarComponents();int subRegion[6] = { 0,300, 0, 300, 0, 0 };vtkImageIterator<unsigned char> it(reader->GetOutput(), subRegion);while (!it.IsAtEnd()){unsigned char* inSI = it.BeginSpan();unsigned char* inSIEnd = it.EndSpan();while (inSI!=inSIEnd){*inSI = 255 - *inSI;++inSI;}it.NextSpan();}vtkSmartPointer<vtkImageViewer2> imageViewer =vtkSmartPointer<vtkImageViewer2>::New();imageViewer->SetInputConnection(reader->GetOutputPort());vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();imageViewer->SetupInteractor(renderWindowInteractor);imageViewer->Render();imageViewer->GetRenderer()->ResetCamera();imageViewer->Render();imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);imageViewer->SetSize(640, 480);imageViewer->GetRenderWindow()->SetWindowName("VisitImagePixelIterativelyExample");renderWindowInteractor->Start();}

相关文章:

VTK知识学习(26)- 图像基本操作(一)

1、前言 图像处理离不开一些基本的图像数据操作&#xff0c;例如获取和修改图像的基本信息、访问和修改图像像素值、图像显示、图像类型转换等。熟练掌握这些基本操作有助于使用 VTK进行图像处理应用程序的快速开发。 2、图像信息的访问与修改 1&#xff09;利用vtkIamgeData…...

2024年9月AI头条新闻:创新与挑战并存

2024年9月AI头条新闻&#xff1a;创新与挑战并存 9月&#xff0c;人工智能领域继续高速发展&#xff0c;重大产品发布、伦理争议和技术突破交织在一起。让我们回顾一下本月最重要的AI新闻&#xff1a; OpenAI的o1&#xff1a;更强大的语言模型 OpenAI推出了o1&#xff0c;一个…...

[Xshell] Xshell的下载安装使用、连接linux、 上传文件到linux系统-详解(附下载链接)

前言 xshell 链接&#xff1a;https://pan.quark.cn/s/57062561e81a 提取码&#xff1a;TK4K 链接失效&#xff08;可能被官方和谐&#xff09;可评论或私信我重发 安装 下载后解压得到文件 安装路径不要有中文 打开文件 注意&#xff01;360等软件会拦截创建注册表的行为&a…...

count(1)、count(_)与count(列名)的区别?

大家好&#xff0c;我是锋哥。今天分享关于【count(1)、count(_)与count(列名)的区别&#xff1f;】面试题。希望对大家有帮助&#xff1b; count(1)、count(_)与count(列名)的区别&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 SQL 中&#xff0c…...

代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

贪心没有套路&#xff0c;说白了就是常识性推导加上举反例 今天的内容比较简单 简单了解贪心是通过局部最优解反推全局最优解&#xff08;有经验成分&#xff09; 455.分发饼干 题目链接&#xff1a;455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09; 讲解链接&#xff…...

List直接使用removeAll报错

List直接使用removeAll报错 需要先将list转换才能使用 原因是&#xff1a; removeAll 方法在 Java 中用于从当前列表中删除另一个列表中存在的所有元素。如果直接对 List 接口的一个实现使用 removeAll 方法抛出异常&#xff0c;可能的原因有&#xff1a; 不同的List实现&am…...

Debian环境安装Docker Engine

Debian环境安装Docker Engine 卸载旧版本使用APT工具安装Docker设置存储库安装Docker设置权限 docker compose命令卸载Docker 卸载旧版本 要卸载的非官方软件包是&#xff1a; docker.iodocker-composedocker-docpodman-docker 此外&#xff0c;Docker Engine 依赖 containe…...

Python常用内置函数总结

目录 1. abs() 2. complex() 3. divmod() 4. eval() 5. float() 6. hash() 7. input() 8. int() 9. len() 10. list() 11. oct() 12. open() 13. pow() 14. print() 15. range() 16. reversed() 17. round() 18. sorted()…...

深入了解蓝牙Profile类型与设备的对应关系

在现代技术中,蓝牙作为一种无线通信技术,广泛应用于各种设备之间的短距离通信。不同的设备在连接时使用不同的蓝牙Profile(配置文件),每种Profile都为特定的设备功能提供支持,例如音频流传输、语音通话、文件传输等。在本文中,我们将详细介绍蓝牙Profile的常见类型及其对…...

[bug]java导出csv用Microsoft Office Excel打开乱码解决

[bug]java导出csv用Microsoft Office Excel打开乱码 ‍ 现象 首先这个csv文件用macbook自带的 "Numbers表格" 软件打开是不乱码的, 但是使用者是Windows系统,他的电脑没有"Numbers表格"工具, ​​ 他用Microsoft Office Excel打开之后出现乱码,如下图…...

2023年区块链职业技能大赛——区块链应用技术(一)模块一

模块一:区块链产品方案设计及系统运维: 任务1-1:区块链产品需求分析与方案设计 1.依据给定区块链食品溯源系统的业务架构图&#xff0c;对考题进行业务分析&#xff0c;可能多的去考虑一个业务系统所需要的模块&#xff0c;使用Visio或思维导图工具展现本系统的基本设计概念和…...

4 软件工程——总体设计

一、设计过程 1.两个主要阶段 系统设计阶段&#xff1a;确定系统的具体实现方案结构设计阶段&#xff1a;确定软件结构 2.九个步骤 设想供选择的方案选取合理的方案推荐最佳方案功能分解设计软件结构设计数据库制定测试计划书写文档审查和复审 二、设计原理 1.模块化 模块…...

Elasticsearch:确保业务规则与语义搜索无缝协作

作者&#xff1a;来自 Elastic Kathleen DeRusso 利用查询规则与语义搜索和重新排序相结合的强大功能。 更多阅读&#xff1a; Elasticsearch 8.10 中引入查询规则 - query rules Elasticsearch 查询规则现已正式发布 - query rules 你是否知道查询规则&#xff08;query ru…...

【大语言模型】ACL2024论文-33 Johnny 如何说服大型语言模型越狱:通过人性化 LLMs 重新思考挑战 AI 安全性的说服技巧

【大语言模型】ACL2024论文-33 Johnny 如何说服大型语言模型越狱&#xff1a;通过人性化 LLMs 重新思考挑战 AI 安全性的说服技巧 目录 文章目录 【大语言模型】ACL2024论文-33 Johnny 如何说服大型语言模型越狱&#xff1a;通过人性化 LLMs 重新思考挑战 AI 安全性的说服技巧目…...

【LuaFramework】LuaFramework_UGUI_V2框架学习

GitHub - jarjin/LuaFramework_UGUI_V2: 基于tolua的热更新框架V2 旧版本是Unity 5.0&#xff0c;这个是新版本支持更高版本的 导入工程后先清除wrap 然后重新生成wrap&#xff0c;你会发现有个报空null&#xff0c;框架的问题总结下所有的框架wrap相关报错问题和修复方法&…...

使用 AOP 在 Spring Boot 中实现跟踪和日志记录

在现代应用程序中&#xff0c;尤其是使用微服务构建的应用程序&#xff0c;跟踪和日志记录在跟踪流经各种服务的请求方面起着至关重要的作用。跟踪可帮助开发人员诊断问题、监控性能并了解用户在多个系统中的旅程。 在此博客中&#xff0c;我们将介绍如何使用traceId从前端生成…...

如何永久解决Apache Struts文件上传漏洞

Apache Struts又双叒叕爆文件上传漏洞了。 自Apache Struts框架发布以来&#xff0c;就存在多个版本的漏洞&#xff0c;其中一些漏洞涉及到文件上传功能。这些漏洞可能允许攻击者通过构造特定的请求来绕过安全限制&#xff0c;从而上传恶意文件。虽然每次官方都发布补丁进行修…...

FPGA远程升级 -- FLASH控制

简介 前文讲到如何实现XILINX芯片程序跳转&#xff0c;但升级程序是事先通过VIVADO工具将两个程序合成一个BIN文件实现升级的&#xff0c;并不能在线更新升级。要实现远程升级的能力需要对FPGA的FLASH进行在线写入升级程序。 FLASH介绍 本次设计FLASH选用的是S25FL128芯片&…...

企业内训|高智能数据构建、Agent研发及AI测评技术内训-吉林省某汽车厂商

吉林省某汽车厂商为提升员工在AI大模型技术方面的知识和实践能力&#xff0c;举办本次为期8天的综合培训课程。本课程分为两大部分&#xff1a;面向全体团队成员的AI大模型技术结构与行业应用&#xff0c;以及针对技术团队的高智能数据构建与Agent研发。课程内容涵盖非结构化数…...

ARM异常处理 M33

1. ARMv8-M异常类型及其详细解释 ARMv8-M Exception分为两类&#xff1a;预定义系统异常(015)和外部中断(1616N)。 各种异常的状态可以通过Status bit查看&#xff0c;获取更信息的异常原因&#xff1a; CFSR是由UFSR、BFSR和MMFSR组成&#xff1a; 下面列举HFSR、MMFSR、…...

(补)算法刷题Day24: BM61 矩阵最长递增路径

题目链接 思路 方法一&#xff1a;dfs暴力回溯 使用原始used数组4个方向遍历框架 &#xff0c; 全局添加一个最大值判断最大的路径长度。 方法二&#xff1a;加上dp数组记忆的优雅回溯 抛弃掉used数组&#xff0c;使用dp数组来记忆遍历过的节点的最长递增路径长度。每遍历到已…...

探索 Bokeh:轻松创建交互式数据可视化的强大工具

探索 Bokeh&#xff1a;轻松创建交互式数据可视化的强大工具 在数据科学和数据分析领域&#xff0c;交互式数据可视化是一项不可或缺的技能。Bokeh 是一个强大的 Python 库&#xff0c;它可以帮助我们快速构建高质量的交互式图表和仪表盘&#xff0c;同时兼具高性能和灵活性。…...

【Rust自学】6.1. 定义枚举

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 6.1.1. 什么是枚举 枚举允许我们列举所有可能的值来定义一个类型。这与其他编程语言中的枚举类似&#xff0c;但 Rust 的枚举更加灵活和强…...

【Java基础面试题035】什么是Java泛型的上下界限定符?

回答重点 Java泛型的上下界限定符用于对泛型类型参数进行范围限制&#xff0c;主要有上界限定符和下届限定符。 1&#xff09;上界限定符 (? extends T)&#xff1a; 定义&#xff1a;通配符?的类型必须是T或者T的子类&#xff0c;保证集合元素一定是T或者T的子类作用&…...

0基础学前端系列 -- 深入理解 HTML 布局

在现代网页设计中&#xff0c;布局是至关重要的一环。良好的布局不仅能提升用户体验&#xff0c;还能使内容更具可读性和美观性。HTML&#xff08;超文本标记语言&#xff09;结合 CSS&#xff08;层叠样式表&#xff09;为我们提供了多种布局方式。本文将详细介绍流式布局、Fl…...

【python高级】342-TCP服务器开发流程

CS模式&#xff1a;客户端-服务端模式 TCP客户端开发流程介绍&#xff08;五步&#xff09;&#xff08;C端&#xff09; 1.创建客户端套接字对象 2.和服务端套接字建立连接 3.发送数据 4.接收数据 5.关闭客户端套接字 TCP服务端开发流程&#xff08;七步&#xff09;&#xf…...

《计算机组成及汇编语言原理》阅读笔记:p48-p81

《计算机组成及汇编语言原理》学习第 4 天&#xff0c;p48-p81 总结&#xff0c;总计 34 页。 一、技术总结 1.CISC vs RISC p49&#xff0c; complex instruction set computing For example, a complex instruction set computing (CISC) chip may be able to move a lar…...

AI在传统周公解梦中的技术实践与应用

本文深入探讨了人工智能在传统周公解梦领域的技术实践与应用。首先介绍了传统周公解梦的背景与局限性&#xff0c;随后详细阐述了 AI 技术如何应用于梦境数据的采集、整理与分析&#xff0c;包括自然语言处理技术对梦境描述的理解&#xff0c;机器学习算法构建解梦模型以及深度…...

GIS数据处理/程序/指导,街景百度热力图POI路网建筑物AOI等

简介其他数据处理/程序/指导&#xff01;&#xff01;&#xff01;&#xff08;1&#xff09;街景数据获取&#xff08;2&#xff09;街景语义分割后像素提取&#xff0c;指标计算代码&#xff08;绿视率&#xff0c;天空开阔度、视觉熵/景观多样性等&#xff09;&#xff08;3…...

ssr实现方案

目录 序言 一、流程 二、前端要做的事情 三、节点介绍 四、总结 序言 本文不是详细的实现过程&#xff0c;是让你最快最直接的理解ssr的真正实现方法&#xff0c;有前端经验的同学&#xff0c;能够很好的理解过程&#xff0c;细节根据具体项目实现 一、前端要做的事情 1.…...