【VTK学习笔记-08】VTK图像基本操作(图像信息/像素值的访问与修改、图像类型转换、颜色映射、区域提取、直方图统计、重采样、图像运算、二值化)

学习教程:《VTK图形图像开发进阶》张晓东,罗火灵
特别感谢:东灵工作室

5.3 VTK图像基本操作

5.3.1 图像信息的访问与修改

(1)vtkImageData——图像信息访问

vtkImageData提供了多个函数用于获取图像的基本信息,通常是以Set或Get加上相应的信息名的形式命名。

示例:
读入一幅bmp格式的二维图像,显示获取的图像维数、图像原点和像素间隔信息。

源码:

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageViewer2.h>
#include <vtkBMPReader.h>

//测试图像:../data/lena.bmp
int main()
{
    
    
	//读取bmp图像
	vtkSmartPointer<vtkBMPReader>reader = vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("../data/lena.bmp");
	reader->Update();

	//获取图像信息
	int dims[3];
	reader->GetOutput()->GetDimensions(dims);
	std::cout << "图像维数" << dims[0] << " " << dims[1] << " " << dims[2] << std::endl;

	double origin[3];
	reader->GetOutput()->GetOrigin(origin);
	std::cout << "图像原点" << origin[0] << " " << origin[1] << " " << origin[2] << std::endl;

	double spacing[3];
	reader->GetOutput()->GetSpacing(spacing);
	std::cout << "像素间隔" << spacing[0] << " " << spacing[1] << " " << spacing[2] << std::endl;

	//显示图像 
	vtkSmartPointer<vtkImageViewer2>imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
	imageViewer->SetInputConnection(reader->GetOutputPort());

	vtkSmartPointer<vtkRenderWindowInteractor>renWinInter = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	imageViewer->SetupInteractor(renWinInter);
	imageViewer->Render();
	imageViewer->GetRenderer()->ResetCamera();
	imageViewer->Render();

	imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
	imageViewer->SetSize(640, 480);
	imageViewer->GetRenderWindow()->SetWindowName("GetImageInformationExample");

	renWinInter->Start();

	return 0;
}

结果:
在这里插入图片描述

注意: VTK中无论是二维还是三维图像,都用vtkImageData表示,因此程序中定义图像维数为dims[3]。

(2)vtkChangeImageInformation——图像信息修改

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

源码:

#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkBMPReader.h>
#include <vtkImageChangeInformation.h>
#include <vtkImageData.h>

//测试图像:../data/lena.bmp
int main()
{
    
    
	//读取图像
	vtkSmartPointer<vtkBMPReader>reader = vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("../data/lena.bmp");
	reader->Update();

	int dims[3];
	double origin[3];
	double spacing[3];

	//查看图像原始信息
	reader->GetOutput()->GetDimensions(dims);
	std::cout << "原图像维数" << dims[0] << " " << dims[1] << " " << dims[2] << std::endl;
	reader->GetOutput()->GetOrigin(origin);
	std::cout << "原图像原点" << origin[0] << " " << origin[1] << " " << origin[2] << std::endl;
	reader->GetOutput()->GetSpacing(spacing);
	std::cout << "原图像像素间隔" << spacing[0] << " " << spacing[1] << " " << spacing[2] << std::endl;

	//修改图像
	vtkSmartPointer<vtkImageChangeInformation>changer = vtkSmartPointer<vtkImageChangeInformation>::New();
	changer->SetInputData(reader->GetOutput());
	changer->SetOutputOrigin(100, 100, 0);  //将图像原点置为(100,100)
	changer->SetOutputSpacing(5, 5, 1);
	changer->SetCenterImage(1);//该函数的作用是将(0,0,0)置为图像的中心。将会覆盖上述设置的SetOutputOrigin(100, 100, 0)
	changer->Update();

	//查看图像修改后信息
	changer->GetOutput()->GetDimensions(dims);
	std::cout << "修改后图像维数:" << dims[0] << " " << dims[1] << " " << dims[2] << std::endl;
	changer->GetOutput()->GetOrigin(origin);
	std::cout << "修改后图像原点:" << origin[0] << " " << origin[1] << " " << origin[2] << std::endl;
	changer->GetOutput()->GetSpacing(spacing);
	std::cout << "修改后像素间隔:" << spacing[0] << " " << spacing[1] << " " << spacing[2] << std::endl;

	//显示修改后的图像
	vtkSmartPointer<vtkImageViewer2> imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
	imageViewer->SetInputConnection(changer->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("ImageChangeInformationExample");

	renderWindowInteractor->Start();

	return 0;
}

结果:
在这里插入图片描述

5.3.2 图像像素值的访问与修改

图像像素值的访问与修改是最常用的一种操作。VTK中提供了两种方法。

(1)直接访问vtkImageData的数据数组——通过GetScalarPointer()函数获取数据数组指针

vtkImageData中提供了GetScalarPointer()函数获取数据数组指针,该函数有三种形式:

//根据给定的像素索引得到指定的像素值,返回的是第(x,y,z)个像素值的地址
virtual void *GetScalarPointer(int coordinates[3]); 
virtual void *GetScalarPointer(int x,int y,int z); 

//返回图像数据数组的头指针,根据头指针可以依次访问索引像素
virtual void *GetScalarPointer();

示例:
将图像的100×100大小的区域设置为黑色。

源码:

#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkBMPReader.h>
#include <vtkImageData.h>

//测试图像:../data/lena.bmp
int main()
{
    
    
	//读取图像
	vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("../data/lena.bmp");
	reader->Update();

	//图像大小
	int dims[3];
	reader->GetOutput()->GetDimensions(dims);

	//获取图像的元组组分数(是灰度图、梯度图、还是RGB图)
	int nbOfComp;
	nbOfComp = reader->GetOutput()->GetNumberOfScalarComponents();

	//三重循环遍历像素点
	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)
				{
    
    
					//GetScalarPointer返回的是void类型,因此需要根据图像的实际类型进行强制转换。
					//如果是RGB图,获取R值地址
					unsigned char * pixel = (unsigned char *)(reader->GetOutput()->GetScalarPointer(i, j, k));
					*pixel = 0;
					*(pixel + 1) = 0;  //(pixel + 1)即为G值的地址
					*(pixel + 2) = 0;  //(pixel + 2)即为B值的地址
				}
			}
		}
	}

	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("VisitImagePixelDirectlyExample");

	renderWindowInteractor->Start();

	return 0;
}

结果:
在这里插入图片描述

注意:
GetScalarPointer()函数返回的是void *类型,需要根据图像的实际类型进行强制转换。如果对数据类型不确定,还可以将图像数据类型强制转换为特定的数据类型,再进行遍历。

在修改RGB图像以及矢量图像像素时,需要根据像素的元组的组分数目来访问。先访问第(i,j,k)个像素的R值的地址,再依次地址加一访问后面G值、B值。

(2)vtkImageIterator——迭代器方法访问图像像素

该类是一个模板类,使用时需要提供迭代的图像像素类型以及迭代的区域大小。

示例:
读入一幅bmp格式的图像,将图像中300×300区域的像素值取反。

源码:

#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkBMPReader.h>
#include <vtkImageData.h>
#include <vtkImageIterator.h>

//测试图像:../data/lena.bmp
int main()
{
    
    
	//1.读取图像
	vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("../data/lena.bmp");
	reader->Update();

	//2.迭代访问像素值 二重循环

	//定义一个子区域,不能超过图像范围(xmin,xmax,ymin,ymax,zmin,zmax)
	//根据图像类型unsigned char定义一个图像迭代器it,两个参数(要访问的图像,要访问的图像子区域)
	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(); //该点像素的最后一个组分

		//判断当前像素的元组Tuple是否迭代完毕
		while (inSI != inSIEnd)
		{
    
    
			*inSI = 255 - *inSI;
			++inSI; //不断迭代当前像素的组分
		}

		it.NextSpan(); //该像素点组分迭代完毕后,继续迭代下个像素的组分元组
	}

	//3.显示图像
	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();

	return 0;

}

结果:
在这里插入图片描述

5.3.3 图像类型转换

(1)vtkImageCast——最简单的类型转换Filter,不推荐使用

使用方法如下,只需要将SetOutputScalarTypeToxxx()设置成相应的输出类型即可。

该类中还有一个变量ClampOverflow,用来标识是否需要截断数据,默认情况下,该变量值为0.当设置其值为1时,输出的像素值不能超过输出类型的最大值,超过时自动截断至最大值。

因此,该类在进行类型转换时,只是将数据进行强制转换,而没有进行比例的缩放,使用受限,VTK中也不推荐使用该类。

vtkSmartPointer<vtkImageCast>imageCast=vtkSmartPointer<vtkImageCast>::New();
imageCast->SetInput((vtkDataObject*)reader->GetOutput());
imageCast->SetOutputScalarTypeToFloat();
imageCast->Update();

(2)vtkImageShiftScale——指定偏移和比例参数

vtkImageShiftScale可以指定偏移和比例参数来对输入图像数据进行操作。

例如:将一幅double类型的图像,其数值范围是[-1,1],如果将其转换为unsigned char类型,需要设置shift值为+1,比例系数设置为127.5,那么输入数据为-1的映射为(-1+1)×127.5=0,而+1则会映射为(+1+1)×127.5=255。具体代码如下:

vtkSmartPointer<vtkImageShiftScale>shiftScaleFilter=vtkSmartPointer<vtkImageShiftScale>::New();
shiftScalarFilter->SetInputConnection(image->GetProducerPort());
shiftScalarFilter->SetOutputScalarTypeToUnsignedChar();
shiftScalarFilter->SetShift(1);  //设置偏移量
shiftScalarFilter->SetScale(127.5);  //设置缩放值
shiftScalarFilter->Update();

注意:
该类中也有一个变量ClampOverflow,当其值为1时,如果输出值超过输出类型的最大值时,则自动截断。例如,输出类型为unsigned char,数值范围是0~255,当输出像素为257时,该类会自动截断为255。默认情况下,变量ClampOverflow的值为0,此时,当输出值为257时,输出类型为unsigned char时,该类不会将其截断,而是会溢出,最后取值为2

5.3.4 图像颜色映射

(1)vtkImageLuminance——灰度映射

vtkImageLuminance负责将一个RGB彩色图像转换为一个单组分的灰度图像。映射公式为:
在这里插入图片描述
该公式用于计算一个RGB颜色的亮度。
该类的使用代码如下:

vtkSmartPointer<vtkImageLuminance>luminanceFilter=vtkSmartPointer<vtkImageLuminance>::New();
luminanceFilter->SetInputConnection(reader->GetOutputPort());
luminanceFilter->Update();

在这里插入图片描述

(2)vtkImageExtractComponents——提取颜色组分

提取彩色图像的各个颜色组分,使用该类时需要设置要提取的组分序号即可。

(3)vtkImageMapToColors——彩色映射

图像彩色映射的原理是:先生成一个颜色查找表,然后根据图像像素的一个标量值在颜色查找表中查找对应的颜色,并用新颜色值代替原来的像素值。VTK中以vtkImageMapToColors实现图像彩色映射,以vtkLookUpTable生成颜色查找表。

//读入灰度图像
vtkSmartPointer<vtkJPEGReader>reader=vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName("../data/lena.jpg");

//生成颜色查找表
vtkSmartPointer<vtkLookupTable>colorTable=vtkSmartPointer<vtkLookupTable>::New();
colorTable->SetRange(0.0,255.0);//设置要映射的标量数据的范围
colorTable->SetHueRange(0.1,0.5);//设置HSV颜色空间的Hue值范围,最大范围[0,1]
colorTable->SetValueRange(0.6,1.0);//设置HSV颜色空间的Value值范围,最大范围[0,1]
colorTable->Build();//生成颜色查找表

//根据颜色查找表来查找新颜色,并替换
vtkSmartPointer<vtkImageMapToColors>colorMap=vtkSmartPointer<vtkImageMapToColors>::New();
colorMap->SetInputConnection(reader->GetOutputPort());
colorMap->SetLookupTable(colorTable);//设置相应的颜色查找表
colorMap->Update();

(4)vtkImageAppendComponents——颜色合成

将多个灰度图像合并成一个彩色图像。vtkImageAppendComponents类可用来合成彩色图像,需要输入提供三个灰度图像。
在这里插入图片描述

就好比,单通道的二值图像,三个通道叠加即可形成彩色图像,叠加后的图像像素点的三个值即为该点的RGB值,即可合成颜色。三个通道叠加排列的顺序不一样,显示出来的颜色也不同。
在这里插入图片描述

5.3.5 区域提取

(1)vtkExtractVOI——提取感兴趣区域

根据用户指定的区域范围提取子图像。该Filter的输入和输出都是一个vktImageData,因此其结果可以直接作为图像保存。

定义一个vtkExtractVOI对象,需要接收两个输入,一个是原始图像数据,一个是提取区域大小。

//获取图像大小
int dims[3];
reader->GetOutput()->GetDimensions(dims);

//设定提取的区域大小(xmin,xmax,ymin,ymax,zmin,zmax)
vtkSmartPointer<vtkExtractVOI>extractVOI=vtkSmartPointer<vtkExtractVOI>::New();
extractVOI->SetInputConnection(reader->GetOutputPort());
extractVOI->SetVOI(dims[0]/4.,3.*dims[0]/4.,dims[1]/4.,3.*dims[1]/4.,0,0);
extractVOI->Update();

(2)vtkImageReslice——三维图像切面提取(×)

vtkImageReslice可以提取过三维图像内部一点且平行于任意方向的平面。

(3)扩展——滑动鼠标切换三维图像切面(×)

5.3.6 直方图统计(×)

VTK中的vtkImageAccumulate类用于实现直方图统计功能。它将每个组分的数值范围划分为离散的间隔,然后统计每个灰度间隔上的像素数目。其输入输出都是vtkImageData类型,因此直方图也可以看作是一幅图像。收入图像的像素数据类型可以是任意的,但是最大支持3个组分像素类型,而输出图像的像素数据类型为int型。

(1)灰度图像直方图(×)

灰度图像使用该Filter会产生一个一维图像。

(2)彩色图像直方图(×)

彩色图像有三个颜色通道,因此需要提取RGB三个通道数据分别计算直方图。

5.3.7 图像重采样

图像重采样是指对数字图像按所需的位置像素或像素间距重新采样,以构成几何变换后的新图像。

重采样后图像的维数会发生改变。当重采样图像维数小于原图像时,称为降采样;当重采样图像维数大于原图像时,称为升采样。vtkImageShrink3D类可用于实现图像降采样。vtkImageMagnify类可用于实现图像的升采样。

降采样需要设置每个方向的采样率,采样率越大,图像越模糊。升采样的原理与降采样一样,只是通过增加采样点数来增加图像的维数。

采样率为20即20步选一个,所以512×512的图像,经过采样率为20×20的降采样后,图像维数为25×25。

源码:

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageShiftScale.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkBMPReader.h>
#include <vtkImageShrink3D.h>
#include <vtkImageMagnify.h>

//测试图像:../data/lena.bmp
int main()
{
    
    
	//读入图像
	vtkSmartPointer<vtkBMPReader>reader = vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("../data/lena.bmp");
	reader->Update();

	int originalDims[3];
	reader->GetOutput()->GetDimensions(originalDims);
	std::cout << "原图图像维数      :" << originalDims[0] << " " << originalDims[1] << " " << originalDims[2] << std::endl;

	double originalSpace[3];
	reader->GetOutput()->GetSpacing(originalSpace);
	std::cout << "原图图像像素间隔  :" << originalSpace[0] << " " << originalSpace[1] << " " << originalSpace[2] << std::endl;

	//降采样
	vtkSmartPointer<vtkImageShrink3D>shrinkFilter = vtkSmartPointer<vtkImageShrink3D>::New();
	shrinkFilter->SetInputConnection(reader->GetOutputPort());
	shrinkFilter->SetShrinkFactors(20, 20, 1);
	shrinkFilter->Update();

	int shrinkDims[3];
	shrinkFilter->GetOutput()->GetDimensions(shrinkDims);
	std::cout << "降采样图像维数    :" << shrinkDims[0] << " " << shrinkDims[1] << " " << shrinkDims[2] << std::endl;

	double shrinkSpace[3];
	shrinkFilter->GetOutput()->GetSpacing(shrinkSpace);
	std::cout << "降采样图像像素间隔:" << shrinkSpace[0] << " " << shrinkSpace[1] << " " << shrinkSpace[2] << std::endl;

	//升采样
	vtkSmartPointer<vtkImageMagnify> magnifyFilter = vtkSmartPointer<vtkImageMagnify>::New();
	magnifyFilter->SetInputConnection(reader->GetOutputPort());
	magnifyFilter->SetMagnificationFactors(10, 10, 1);
	magnifyFilter->Update();

	int magnifyDims[3];
	magnifyFilter->GetOutput()->GetDimensions(magnifyDims);
	std::cout << "升采样图像维数    :" << magnifyDims[0] << " " << magnifyDims[1] << " " << magnifyDims[2] << std::endl;

	double magnifySpace[3];
	magnifyFilter->GetOutput()->GetSpacing(magnifySpace);
	std::cout << "升采样图像像素间隔:" << magnifySpace[0] << " " << magnifySpace[1] << " " << magnifySpace[2] << std::endl;

	//显示三张图像(原图、降采样、升采样)
	vtkSmartPointer<vtkImageActor>originalActor = vtkSmartPointer<vtkImageActor>::New();
	originalActor->SetInputData(reader->GetOutput());

	vtkSmartPointer<vtkImageActor>shrinkActor = vtkSmartPointer<vtkImageActor>::New();
	shrinkActor->SetInputData(shrinkFilter->GetOutput());
	
	vtkSmartPointer<vtkImageActor>magnifyActor = vtkSmartPointer<vtkImageActor>::New();
	magnifyActor->SetInputData(magnifyFilter->GetOutput());

	double originalViewport[4] = {
    
     0.0, 0.0, 0.33, 1.0 };
	double shrinkViewport[4] = {
    
     0.33, 0.0, 0.66, 1.0 };
	double magnifyViewport[4] = {
    
     0.66, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkRenderer> originalRenderer = vtkSmartPointer<vtkRenderer>::New();
	originalRenderer->SetViewport(originalViewport);
	originalRenderer->AddActor(originalActor);
	originalRenderer->ResetCamera();
	originalRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> shrinkRenderer = vtkSmartPointer<vtkRenderer>::New();
	shrinkRenderer->SetViewport(shrinkViewport);
	shrinkRenderer->AddActor(shrinkActor);
	shrinkRenderer->ResetCamera();
	shrinkRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> magnifyRenderer = vtkSmartPointer<vtkRenderer>::New();
	magnifyRenderer->SetViewport(magnifyViewport);
	magnifyRenderer->AddActor(magnifyActor);
	magnifyRenderer->ResetCamera();
	magnifyRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(originalRenderer);
	renderWindow->AddRenderer(shrinkRenderer);
	renderWindow->AddRenderer(magnifyRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("ImageShrinkMagnifyExample");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();

	renderWindowInteractor->SetInteractorStyle(style);
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindowInteractor->Initialize();
	renderWindowInteractor->Start();

	return 0;
}

结果:
在这里插入图片描述

5.3.8 图像运算

(1)vtkImageMathematics——数学运算

vtkImageMathematics提供了基本的一元和二元数学操作。二元数学操作要求两个输入图像具有相同的像素数据类型和颜色组分。当两个图像大小不同时,输出图像的范围为两个输入图像范围的并集,并且原点和像素间隔与第一个输入图像保持一致。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)vtkImageLogic——逻辑运算

vtkImageLogic接受一个或者两个图像进行布尔逻辑运算,该类主要支持与(AND)、或(OR)、异或(XOR)、与非(NAND)、或非(NOR)、非(NOT)。当选择二元操作符时,两个输入图像的类型必须一致。

5.3.9 图像二值化

二值图像和Label图像是图像分割中经常用到的两种图像。二值图像的每个像素只有两种可能的取值,即0和255。0代表图像的背景,255代表图像的前景。

图像二值化:设置一个灰度阈值,将图像中阈值以下的像素值设置为背景,阈值以上的像素值设置为前景,即可得到一幅二值图像。通过vtkImageThreshold类实现。

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

vtkSmartPointer<vtkImageThreshold> thresholdFilter = vtkSmartPointer<vtkImageThreshold>::New();
thresholdFilter->SetInputConnection(reader->GetOutputPort());

//取大于100的所有像素输出值为255,而小于100的像素输出值为0
thresholdFilter->ThresholdByUpper(100);//取大于100的灰度范围为有效范围
thresholdFilter->SetInValue(255);//设置有效范围内的输出值为255
thresholdFilter->SetOutValue(0);//设置有效范围外的输出值为0

猜你喜欢

转载自blog.csdn.net/m0_51141265/article/details/132861595