VTK知识学习(27)- 图像基本操作(二)

ops/2024/12/23 1:45:07/

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),显示为红色。 


http://www.ppmy.cn/ops/144188.html

相关文章

鸿蒙项目云捐助第十讲鸿蒙App应用分类页面二级联动功能实现

鸿蒙项目云捐助第十讲鸿蒙App应用分类页面二级联动功能实现 在之前的教程中完成了分类页面的左右两侧的列表结构,如下图所示。 接下来需要实现左侧分类导航项的点击操作,可以友好的提示用户选择了哪一个文字分类导航项。 一、左侧文字分类导航的处理 …

Java基本概念6-JVM2

(如上图)各个区域的功能: 方法区:方法区是所有线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。静态方法和变量会提前分配空间,不需要再次分配&#…

解锁报表在线设计新高度:FastReport Online Designer 2025.1 正式上线!

我们非常高兴地向大家宣布,FastReport Online Designer 2025.1 版本正式发布!这一全新的版本不仅进一步优化了用户体验,还引入了众多实用的新功能与改进,帮助您在浏览器中轻松设计模板和报表。以下为您带来本次更新的亮点&#xf…

Element@2.15.14-tree checkStrictly 状态实现父项联动子项,实现节点自定义编辑、新增、删除功能

背景:现在有一个新需求,需要借助树结构来实现词库的分类管理,树的节点是不同的分类,不同的分类可以有自己的词库,所以父子节点是互不影响的;同样为了选择的方便性,提出了新需求,选择…

neo4j 图表数据导入到 TuGraph

neo4j 图表数据导入到 TuGraph 代码文件说明后文 前言:近期在引入阿里的 TuGraph 图数据库,需要将 原 neo4j 数据导入到新的 tugraph 数据库中。预期走csv文件导入导出,但因为格式和数据库设计问题,操作起来比较麻烦(可能是个人没…

Docker搭建kafka环境

系统:MacOS Sonoma 14.1 Docker版本:Docker version 27.3.1, build ce12230 Docker desktop版本:Docker Desktop 4.36.0 (175267) 1.拉取镜像 先打开Docker Desktop,然后在终端执行命令 docker pull lensesio/fast-data-dev …

JAVA队列每次添加需要新实例才能独立更新

JAVA队列每次添加需要新实例才能独立更新 队列里面的实例多次添加同一个实例实例结果 每次添加一个新实例实例结果 队列中添加包装类型实例结果 队列里面的实例 由于JAVA对于Object类型参数传参传递的是地址,实例更新,队列里面的实例也会被更新。关于JA…

Pytorch应用实战(1)- 基于YOLO的视频人脸马赛克处理

免费链接: Blogger(需翻Q), Github 文章目录 本文介绍给图片的人脸打码给视频的人脸打码本文介绍 YoloV11(Github)提供了非常方便的API帮助用户实现目标检测(detect)、语义分割(segement)、肢体识别(Pose)等功能。 本文将基于YoloV11的目标检测来实现一个视频人脸马…