VTK知识学习(27)- 图像基本操作(二)
1、图像类型转换
1)vtkImageCast
图像数据类型转换在数字图像处理中会频繁用到。一些常用的图像算子(例如梯度算子)在计算时出于精度的考虑,会将结果存储为float或double类型,但在图像显示时,一般要求图像为 unsigned char 类型,这时就需要对数据类型进行转换。VTK 中最简单的类型转换 Filter就是 vtkmageCast,其使用方法如下:
vtkImageCast imageCast = vtkImageCast.New();
imageCast.SetInputConnection(reader.GetOutputPort());
imageCast.SetOutputScalarTypeToFloat();
imageCast.Update();
只需要把 SetOutputScalarTypeToxxX()设置成相应的输出类型即可。另外,该类中还有一个变量 ClampOverflow,用来标识是否需要截断数据。默认情况下,该变量值为0。当设置其值为1时,输出的像素值不能超过输出类型的最大值,超过时自动截断至最大值。该类在进行类型转换时,只是将数据进行强制转换,而没有进行比例的缩放,因此使用比较受限制,VTK中也不推荐使用该类。例如一幅 double 类型的图像,其数值范围为[-1,1],如果需要将图像转换为 unsigned char 类,则无法使用该 Filter 进行转换。这时就需要用到 vklmageShifScale。
2)vtkImageShiftScale
指定偏移和比例参数来对输入图像数据进行操作,例如一幅double 类型的图像,其数值范围为[-1,1],如果将其转换为 unsigned char 类型,需要设置 shif值为+1,比例系数设置为 127.5,那么输入数据-1映射为(-1+1)x127.5=0,而+1 则会映射为(+1+1)x127.5=255。对应代码如下:
vtkImageShiftScale imageShiftScale = vtkImageShiftScale.New();
imageShiftScale.SetInputConnection(reader.GetOutputPort());imageShiftScale.SetOutputScalarTypeToUnsignedChar();
imageShiftScale.SetShift(1);
imageShiftScale.SetScale(127.5);
imageShiftScale.Update();
SetShift()函数,用于设置偏移量 Shift
SetScale()函数,用于设置放缩值Scale,如果源图像的像素值为Val,那么输出值为(Val+shif)xScale。
SetOutputScalarTypeToUnsignedChar()用于设置输出类型为 unsigned char,当然,该类也提供了其他输出类型的设置函数。
该类中也有一个变量ClampOverfow,当其值为1时,如果输出值超过输出类型的最大值时,则自动截断。例如,输出类型为 unsigned char,数值范围为 0~255,当输出像素值为 257时,该类会自动截断取值为 255。默认情况下,变量 ClampOverflow 的值为 0,此时,当输出值为 257,输出类型为 unsigned char 时,该类不会将其截断,而是会产生溢出,最后取值为2。
2、图像颜色映射
1)图像灰度映射
vtkImageLuminance 负责将一个RGB 彩色图像转换为一个单组分的灰度图像。映射公
式为:
Luminance=0.3xR+0.59xG+0.11xB
R为输入图像的第一组分(红色),G为第二组分(绿色),B为第三组分(蓝色)。
这个公式用于计算一个RGB颜色的亮度。该类的使用也比较简单,用户无须设置参数。
private void TestColor2Gray()
{vtkBMPReader reader = vtkBMPReader.New();reader.SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena.bmp");reader.Update();vtkImageLuminance luminance = vtkImageLuminance.New();luminance.SetInputData(reader.GetOutput());luminance.Update();vtkImageActor orgActor = vtkImageActor.New();orgActor.SetInputData(reader.GetOutput());vtkImageActor actor = vtkImageActor.New();actor.SetInputData(luminance.GetOutput());vtkRenderer orgRenderer = vtkRenderer.New();orgRenderer.AddActor(orgActor);orgRenderer.SetViewport(0.0, 0.0, 0.5, 1.0);orgRenderer.ResetCamera();orgRenderer.SetBackground(1, 1, 1);vtkRenderer renderer = vtkRenderer.New();renderer.SetViewport(0.5, 0.0, 1.0, 1.0);renderer.AddActor(actor);renderer.ResetCamera();renderer.SetBackground(1, 1, 1);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(orgRenderer);renderWindow.AddRenderer(renderer);renderWindow.Render();
}

2)提取颜色组分
VTK 中利用 vtkImageExtractComponents 可以方便地提取彩色图像的各个颜色组分。使用该类时只需要设置要提取的组分序号即可。
private void TestExtractComponets(){vtkBMPReader reader = vtkBMPReader.New();reader.SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena.bmp");reader.Update();//提取红色对应灰度图像vtkImageExtractComponents extractRed = vtkImageExtractComponents.New();extractRed.SetInputData(reader.GetOutput());extractRed.SetComponents(0);extractRed.Update();//提取绿色对应灰度图像vtkImageExtractComponents extractGreen = vtkImageExtractComponents.New();extractGreen.SetInputData(reader.GetOutput());extractGreen.SetComponents(1);extractGreen.Update();//提取蓝色对应灰度图像vtkImageExtractComponents extractBlue = vtkImageExtractComponents.New();extractBlue.SetInputData(reader.GetOutput());extractBlue.SetComponents(2);extractBlue.Update();vtkImageActor orgActor = vtkImageActor.New();orgActor.SetInputData(reader.GetOutput());vtkImageActor redActor = vtkImageActor.New();redActor.SetInputData(extractRed.GetOutput());vtkImageActor greenActor = vtkImageActor.New();greenActor.SetInputData(extractGreen.GetOutput());vtkImageActor blueActor = vtkImageActor.New();blueActor.SetInputData(extractBlue.GetOutput());vtkRenderer orgRenderer = vtkRenderer.New();orgRenderer.AddActor(orgActor);orgRenderer.SetViewport(0.0, 0.0, 0.25, 1.0);orgRenderer.ResetCamera();orgRenderer.SetBackground(1, 1, 1);vtkRenderer renderer = vtkRenderer.New();renderer.SetViewport(0.25, 0.0, 0.5, 1.0);renderer.AddActor(redActor);renderer.ResetCamera();renderer.SetBackground(1, 1, 1);vtkRenderer renderer2 = vtkRenderer.New();renderer2.SetViewport(0.5, 0.0, 0.75, 1.0);renderer2.AddActor(greenActor);renderer2.ResetCamera();renderer2.SetBackground(1, 1, 1);vtkRenderer renderer3 = vtkRenderer.New();renderer3.SetViewport(0.75, 0.0, 1, 1.0);renderer3.AddActor(blueActor);renderer3.ResetCamera();renderer3.SetBackground(1, 1, 1);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(orgRenderer);renderWindow.AddRenderer(renderer);renderWindow.AddRenderer(renderer2);renderWindow.AddRenderer(renderer3);renderWindow.Render();
}

代码中定义了三个 vtkImageExtractComponents 对象,分别用来提取红、绿和蓝色组分图像,函数 SetComponents()用来设置要提取的组分号,红、绿、蓝三色分别对应0、1和2。设置完毕,执行Update()即可得到各个组分的数据。其输出为vtkImageData,每一个颜色组分数据即是一个灰度图像。
3)图像彩色映射
图像彩色映射的原理是:先生成一个颜色查找表,然后根据图像像素的一个标量值在颜色查找表中查找对应的颜色,并用新颜色值替代原来的像素值。VTK中以vkImageMapToColors 实现图像彩色映射,以 vkookUpTable 生成颜色查找表。
private void TestGray2Color(){vtkJPEGReader reader = vtkJPEGReader.New();reader.SetFileName("F:\\code\\VTK\\TestActiViz\\bin\\Debug\\data\\lena-gray.jpg");reader.Update();vtkLookupTable colorTable = vtkLookupTable.New();colorTable.SetRange(0, 255);colorTable.SetHueRange(0.1, 0.5);colorTable.SetValueRange(0.6, 1);colorTable.Build();vtkImageMapToColors colorMap = vtkImageMapToColors.New();colorMap.SetInputData(reader.GetOutput());colorMap.SetLookupTable(colorTable);colorMap.Update();vtkImageActor orgActor = vtkImageActor.New();orgActor.SetInputData(reader.GetOutput());vtkImageActor redActor = vtkImageActor.New();redActor.SetInputData(colorMap.GetOutput());vtkRenderer orgRenderer = vtkRenderer.New();orgRenderer.AddActor(orgActor);orgRenderer.SetViewport(0.0, 0.0, 0.5, 1.0);orgRenderer.ResetCamera();orgRenderer.SetBackground(1, 1, 1);vtkRenderer renderer = vtkRenderer.New();renderer.SetViewport(0.5, 0.0, 1, 1.0);renderer.AddActor(redActor);renderer.ResetCamera();renderer.SetBackground(1, 1, 0.8);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(orgRenderer);renderWindow.AddRenderer(renderer);renderWindow.Render();}

示例先读取了一幅灰度图像,然后生成 vtkLookUpTable 颜色查找表。
构造颜色查找表有两种方法:一种是直接添加颜色;另一种是设置HSV颜色空间变化范围,然后自动生成颜色表。这里采用的是第二种方法,
SetRange()设置要映射的标量数据的范围:
SetHueRange()设置HSV 颜色空间的 Hue 值范围,最大范围为[0,1];
SetValueRange()设置 HSV 颜色空间的 Value 范围,最大范围为[0,1]:
设置完后,调用 Build()来生成颜色査找表。接着定义 vkImageMapToColors 对象,vtkImageMapToColors::SetLookupTable()设置相应的颜色查找表,执行 Update()后,其输出为一幅彩色图像。
4)颜色合成
VTK也支持将多个灰度图像合并成一个彩色图像。VTK 中的 vtkImageAppendComponents 类可用来合成彩色图像,其输入需要提供三个灰度图像。
private void TestColorAppend(){vtkImageCanvasSource2D red = vtkImageCanvasSource2D.New();red.SetScalarTypeToUnsignedChar();red.SetNumberOfScalarComponents(1);red.SetExtent(0, 100, 0, 100, 0, 0);red.SetDrawColor(0, 0, 0, 0);red.FillBox(0, 100, 0, 100);red.SetDrawColor(255, 0, 0, 0);red.FillBox(20, 40, 20, 40);red.Update();vtkImageCanvasSource2D green = vtkImageCanvasSource2D.New();green.SetScalarTypeToUnsignedChar();green.SetNumberOfScalarComponents(1);green.SetExtent(0, 100, 0, 100, 0, 0);green.SetDrawColor(0, 0, 0, 0);green.FillBox(0, 100, 0, 100);green.SetDrawColor(255, 0, 0, 0);green.FillBox(30, 50, 30, 50);green.Update();vtkImageCanvasSource2D blue = vtkImageCanvasSource2D.New();blue.SetScalarTypeToUnsignedChar();blue.SetNumberOfScalarComponents(1);blue.SetExtent(0, 100, 0, 100, 0, 0);blue.SetDrawColor(0, 0, 0, 0);blue.FillBox(0, 100, 0, 100);blue.SetDrawColor(255, 0, 0, 0);blue.FillBox(40, 60, 40, 60);blue.Update();vtkImageAppendComponents components = vtkImageAppendComponents.New();components.SetInputData(0, red.GetOutput());components.AddInputData(0, green.GetOutput());components.AddInputData(0, blue.GetOutput());components.Update();vtkImageActor redActor = vtkImageActor.New();redActor.SetInputData(red.GetOutput());vtkImageActor greenActor = vtkImageActor.New();greenActor.SetInputData(green.GetOutput());vtkImageActor blueActor = vtkImageActor.New();blueActor.SetInputData(blue.GetOutput());vtkImageActor combinedActor = vtkImageActor.New();combinedActor.SetInputData(components.GetOutput());vtkRenderer redRenderer = vtkRenderer.New();redRenderer.AddActor(redActor);redRenderer.SetViewport(0.0, 0.0, 0.25, 1.0);redRenderer.ResetCamera();redRenderer.SetBackground(1, 1, 1);vtkRenderer greenRenderer = vtkRenderer.New();greenRenderer.AddActor(greenActor);greenRenderer.SetViewport(0.25, 0.0, 0.5, 1.0);greenRenderer.ResetCamera();greenRenderer.SetBackground(1, 1, 1);vtkRenderer blueRenderer = vtkRenderer.New();blueRenderer.AddActor(blueActor);blueRenderer.SetViewport(0.5, 0.0, 0.75, 1.0);blueRenderer.ResetCamera();blueRenderer.SetBackground(1, 1, 1);vtkRenderer CombinedRenderer = vtkRenderer.New();CombinedRenderer.SetViewport(0.75, 0.0, 1, 1.0);CombinedRenderer.AddActor(combinedActor);CombinedRenderer.ResetCamera();CombinedRenderer.SetBackground(1, 1, 0.8);vtkRenderWindow renderWindow = renderWindowControl.RenderWindow;renderWindow.AddRenderer(redRenderer);renderWindow.AddRenderer(greenRenderer);renderWindow.AddRenderer(blueRenderer);renderWindow.AddRenderer(CombinedRenderer);renderWindow.Render();}

先利用 vtkImageCanvasSource2D定义了三个二值图像,每个图像中绘制了一个白色矩形,并且三个矩形有部分重叠;然后定义vkImageAppendComponents对象,并将三个图像设置为 vtkImageAppendComponents 对象的输入来合成图像。合成的效果为三个图像中对应的三个像素点的像素值合成一个RGB 像素值,如三个图像中第100个像素的像素值分别为255、0和 0,那么该点在输出图像中的像素值为(255.0.0),显示为红色。
相关文章:
VTK知识学习(27)- 图像基本操作(二)
1、图像类型转换 1)vtkImageCast 图像数据类型转换在数字图像处理中会频繁用到。一些常用的图像算子(例如梯度算子)在计算时出于精度的考虑,会将结果存储为float或double类型,但在图像显示时,一般要求图像为 unsigned char 类型,…...
MyBatis如何处理延迟加载?
大家好,我是锋哥。今天分享关于【MyBatis如何处理延迟加载?】面试题。希望对大家有帮助; MyBatis如何处理延迟加载? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MyBatis 支持 延迟加载(Lazy Loading&am…...
前端网络之【浏览器跨域问题分析与解决方案】
文章目录 同源策略同源与异源跨域的限制场景解决方案 CORS 请求分类 简单请求预检请求 注意点一 【关于Cookie】注意点二 【关于跨域获取响应头】 JSONP 基本流程 代理服务器 如何选择对应方案 同源策略 **同源策略是一套浏览器的安全策略机制,当一个源的文档和脚…...
LeetCode:3218. 切蛋糕的最小总开销 I(贪心 Java)
目录 3218. 切蛋糕的最小总开销 I 题目描述: 实现代码与解析: 贪心 原理思路: 3218. 切蛋糕的最小总开销 I 题目描述: 有一个 m x n 大小的矩形蛋糕,需要切成 1 x 1 的小块。 给你整数 m ,n 和两个数…...
前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案
目录 场景还原 相关代码开发者工具 - 网络请求记录 问题排查 定位改bug 总结 场景还原 我在前端使用axios接收后端xlsx表格文件流并下载,xlsx文件能够下载成功,但是打开却显示文件无法打开 相关代码 请求API封装:Content–Type以及responseType经核…...
PageRank Web页面分级算法 HNUST【数据分析技术】(2025)
1.理论知识 算法原理PageRank 通过网络浩瀚的超链接关系来确定一个页面的等级。 Google 把从 A 页面到 B 页面的链接解释为A页面给B页面投票, Google 根据投票来源(甚至来源的来源, 即链接到A页面的页面)和投票目标的等级来决定新…...
数字IC前端学习笔记:脉动阵列的设计方法学(四)
相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 引言 脉动结构(也称为脉动阵列)表示一种有节奏地计算并通过系统传输数据的处理单元(PEs)网络。这些处理单元有规律地泵入泵出数据以保持规则…...
对话 Project Astra 研究主管:打造通用 AI 助理,主动视频交互和全双工对话是未来重点
Project Astra 愿景之一:「系统不仅能在你说话时做出回应,还能在持续的过程中帮助你。」 近期,Google DeepMind 的 YouTube 频道采访了 Google DeepMind 研究主管格雷格韦恩 (Greg Wayne)。 格雷格韦恩的研究工作为 DeepMind 的诸多突破性成…...
NetApp 存储设备巡检作业指导书
NetApp 存储设备巡检作业指导书 一、目的 本指导书旨在指导管理员通过 SSH 或 Console 登录 NetApp FAS2552 存储系统,切换节点并进行日常管理操作。 二、适用范围 适用于基于 NetApp ONTAP 操作系统的 FAS2552 存储环境。 三、前提条件 网络和权限要求࿱…...
adb无法连接到安卓设备【解决方案】报错:adb server version (40) doesn‘t match this client (41);
下载老版本Platformtoolshttps://dl.google.com/android/repository/platform-tools_r28.0.2-windows.zip?hlzh-cn 替换原来的platform-tools文件夹即可。 问题原因分析:电脑端adb client版本(41)和安卓端adb …...
每天五分钟机器学习:核函数
本文重点 在学习支持向量机算法之前,我们要继续学习一些数学基础,本文我们将学习核函数的概念。当数据线性不可分的时候,此时就需要核函数出场了,它可以将低维不可分的数据映射到高维可分数据,此时就可以完成数据分类了。 核函数的定义 核函数K(x, y)定义为两个数据点x…...
Word窗体联动Excel实现级联组合框
在Word中的使用用户窗体(UserForm)定制界面如下图所示,其中控件如下(忽略Label控件): CompanyName 组合框Attention 组合框CommandButton1 按钮 现在需要实现级联组合框效果,即用户在 CompanyN…...
RAG实战:构建基于本地大模型的智能问答系统
RAG实战:构建基于本地大模型的智能问答系统 引言 在当今AI快速发展的时代,如何构建一个既智能又可靠的问答系统是一个重要课题。本文将介绍如何使用RAG(检索增强生成)技术,结合本地大模型,构建一个高效的智…...
Docker 部署 plumelog 最新版本 实现日志采集
1.配置plumelog.yml version: 3 services:plumelog:#此镜像是基于plumelog-3.5.3版本image: registry.cn-hangzhou.aliyuncs.com/k8s-xiyan/plumelog:3.5.3container_name: plumelogports:- "8891:8891"environment:plumelog.model: redisplumelog.queue.redis.redi…...
TCP/IP 邮件
TCP/IP邮件是互联网通信中非常重要的应用之一。当我们发送电子邮件时,我们实际上并没有直接使用TCP/IP协议,而是通过电子邮件程序,例如微软的Outlook、莲花软件的Notes或Netscape Communicator等来实现。这些电子邮件程序背后使用了不同的TCP…...
FreeSql
官网 实体特性 Ado 它包括所有对 SQL 操作的封装,提供 ExecuteReader、ExecuteDataSet、ExecuteDataTable、ExecuteNonQuery、ExecuteScalar 等方法,使用起来和传统 SqlHelper 一样。 1、安装包 Install-Package FreeSql Install-Package FreeSql.Prov…...
记一次前端Vue项目国际化解决方案
背景 有一个vue项目,要实现国际化功能,能够切换中英文显示,因为该项目系统的用户包括了国内和国外用户。 需求 1、页面表单上的所有中文标签要国际化,包括表单属性标签、表格列头标签等, title“数量”;…...
JS进阶-手写Promise
一、什么是Promise 在Promise A规范中规定,Promise是一个有一个符合规范的then方法的对象或者函数。 1.关于then then接收onFulfilled和onRejected两个可选参数;then必须返回一个新的Promise对象;如果onFulfilled是一个函数 在状态切换为f…...
PCL点云库入门——PCL库点云滤波算法之直通滤波(PassThrough)和条件滤波(ConditionalRemoval)
0、滤波算法概述 PCL点云库中的滤波算法是处理点云数据不可或缺的一部分,它们能够有效地去除噪声、提取特征或进行数据降维。例如,使用体素网格滤波(VoxelGrid)可以减少点云数据量,同时保留重要的形状特征。此外&#…...
ioctl回顾
一、ioctl协议的命令组成 cmd本质为一个32位的数字,共分为四段: [31-30]:读写方向dir,分为无数据(_IO)、读数据(_IOR)、写数据(_IOW)、读写数据(_IOWR)四种模式; [29-16]:传递数据的大小size,一般利用其宏_IO、_IOR…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
