5.3.8 图像运算

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kateyabc/article/details/80914294

1、数学运算

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

#include <vtkMath.h>
#include <vtkSmartPointer.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageMathematics.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>

int main(int, char *[])
{
	vtkSmartPointer<vtkImageCanvasSource2D> imageSource = vtkSmartPointer<vtkImageCanvasSource2D>::New();//创建的画布图像
	imageSource->SetNumberOfScalarComponents(3);
	imageSource->SetScalarTypeToUnsignedChar();
	imageSource->SetExtent(0, 4, 0, 4, 0, 0);
	imageSource->SetDrawColor(100.0, 0, 0);
	imageSource->FillBox(0, 4, 0, 4);
	imageSource->Update();

	vtkSmartPointer<vtkImageMathematics> imageMath = vtkSmartPointer<vtkImageMathematics>::New();
	imageMath->SetOperationToMultiplyByK();//将图像中所有像素值乘以常数K
	imageMath->SetConstantK(2.0);
	imageMath->SetInputConnection(imageSource->GetOutputPort());
	imageMath->Update();

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

	vtkSmartPointer<vtkImageActor> mathActor = vtkSmartPointer<vtkImageActor>::New();
	mathActor->SetInputData(imageMath->GetOutput());

	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

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

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

	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(originalRenderer);
	renderWindow->AddRenderer(gradientMagnitudeRenderer);
	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("ImageMathematicsExample");

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

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

	return EXIT_SUCCESS;
}
运行结果:


上例中生成了一副图像,图像中绘制了一个暗红色矩形;然后定义vtkImageMathematics对象,并调用SetOperationToMultiplyByK()函数来将图像中所有的像素值乘以一个常数K,这里常数值为2.0

vtkImageMathematics中支持的二元数学操作有:

SetOperationToAdd:两个图像对应像素加法运算

SetOperationToSubtract:两个图像对应像素减法运算

SetOperationToMultiply:两个图像对应像素相乘运算

SetOperationToDivide:两个图像对应像素相除运算

SetOperationToConjugate:将两个标量图像对应像素组合为共轭复数

SetOperationToComplexMultiply:两个图像对应像素复数乘法运算

SetOperationToMin:取两个图像中对应像素较小值

SetOperationToMax:取两个图像中对应像素较大值

一元操作有:

SetOperationToInvert:图像像素值取倒数运算

SetOperationToSin:图像像素值正弦运算

SetOperationToCos:图像像素值余弦运算

SetOperationToExp:图像像素值自然指数运算

SetOperationToLog:图像像素值自然对数运算

SetOperationToAbsoluteValue:图像像素值取绝对值

SetOperationToSquare:图像像素值平方运算

SetOperationToSquareRoot:图像像素值平凡根运算

SetOperationToATAN:图像像素值正切运算

SetOperationToATAN2:图像像素值反正切运算

SetOperationToMultiplyByK:图像像素值乘以常数K,需要先调用SetConstantK()设置K值

SetOperationToAddConstant:图像像素值加上常数K,需要先调用SetConstantK()设置K值

SetOperationToReplaceCByK:将图像中像素为C的像素值替换为K,需要先调用SetConstantK()和SetConstantC设置K和C值

2、逻辑运算

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

/*逻辑运算*/
#include <vtkSmartPointer.h>
#include <vtkMath.h>   //
#include <vtkImageData.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageLogic.h>   //
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>

int main(int, char *[])
{
	vtkSmartPointer<vtkImageCanvasSource2D> imageSource1 =	vtkSmartPointer<vtkImageCanvasSource2D>::New();
	imageSource1->SetScalarTypeToUnsignedChar();
	imageSource1->SetNumberOfScalarComponents(1);
	imageSource1->SetExtent(0, 100, 0, 100, 0, 0);
	imageSource1->SetDrawColor(0.0);
	imageSource1->FillBox(0, 100, 0, 100);
	imageSource1->SetDrawColor(255);
	imageSource1->FillBox(20, 60, 20, 60);
	imageSource1->Update();

	vtkSmartPointer<vtkImageCanvasSource2D> imageSource2 =	vtkSmartPointer<vtkImageCanvasSource2D>::New();
	imageSource2->SetNumberOfScalarComponents(1);
	imageSource2->SetScalarTypeToUnsignedChar();
	imageSource2->SetExtent(0, 100, 0, 100, 0, 0);
	imageSource2->SetDrawColor(0.0);
	imageSource2->FillBox(0, 100, 0, 100);
	imageSource2->SetDrawColor(255.0);
	imageSource2->FillBox(40, 80, 40, 80);
	imageSource2->Update();

	vtkSmartPointer<vtkImageLogic> imageLogic =	vtkSmartPointer<vtkImageLogic>::New();
	imageLogic->SetInput1Data(imageSource1->GetOutput());
	imageLogic->SetInput2Data(imageSource2->GetOutput());
	imageLogic->SetOperationToXor();
	imageLogic->SetOutputTrueValue(128);
	imageLogic->Update();

	vtkSmartPointer<vtkImageActor> originalActor1 =	vtkSmartPointer<vtkImageActor>::New();
	originalActor1->SetInputData(imageSource1->GetOutput());

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

	vtkSmartPointer<vtkImageActor> logicActor =	vtkSmartPointer<vtkImageActor>::New();
	logicActor->SetInputData(imageLogic->GetOutput());

	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 };

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

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

	vtkSmartPointer<vtkRenderer> logicRenderer = vtkSmartPointer<vtkRenderer>::New();
	logicRenderer->SetViewport(rightViewport);
	logicRenderer->AddActor(logicActor);
	logicRenderer->ResetCamera();
	logicRenderer->SetBackground(0.6, 0.6, 0.6);

	vtkSmartPointer<vtkRenderWindow> renderWindow =	vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(originalRenderer1);
	renderWindow->AddRenderer(originalRenderer2);
	renderWindow->AddRenderer(logicRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("ImageLogicExample");

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

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

	return EXIT_SUCCESS;
}

运行结果:


上例中首先生成了两个二值图像,两个图像中前景为两个部分重叠矩形。然后定义vtkImageLogic对象,并设置两个图像为输入,SetOperationToXor()设置逻辑操作算子为异或操作,并且SetOutputTrueValue()设置当两个图像对应像素值异或结果为真时的输出像素值,其执行结果如下,可以看成两个矩形的重叠部分像素值相同,因此输出为0;矩形的不重叠部分像素值一个为0,一个为255,因此异或结果为真,那么输出值为128。

vtkImageLogic设置逻辑运算的函数有:

SetOperationToAnd():逻辑与操作

SetOperationToOr():逻辑或操作

SetOperationToXor():逻辑异或

SetOperationToNand():逻辑与非

SetOperationToNor():逻辑或非

SetOperationToNot():逻辑非

注:imageLogic->SetInput1Data(imageSource1->GetOutput());
       imageLogic->SetInput2Data(imageSource2->GetOutput());

vtkImageShrink3D通过SetShrinkFactors()设置X、Y和Z方向的采样率,参数为三个int类型数据。vtkImageMagnify通过SetMagnificationFactors设置相应的放大采样率。从图中可以看成,重采样图像已经变得十分模糊了。而升采样图像则变化不大。程序中输出了原图和重采样图像的维数和像素间隔,从输出来看,原图像的维数为512x512,缩小16倍后,图像维数变为32x32。需要注意的是,原图的像素间隔为(1,1,1),而重采样后像素间隔变为(16, 16, 1),这是因为采样是在世界坐标系下进行的,当采样图像的维数减小时,采样的像素间隔也相应的变大,这样保持图像的区域不会发生改变。同样的道理,当升采样后图像的维数变为原来的10倍,而像素间隔变为原来的十分之一。

注:此文知识学习笔记,仅记录完整程序和实现结果,具体原理参见:

https://blog.csdn.net/www_doling_net/article/details/8541534

https://blog.csdn.net/shenziheng1/article/category/6114053/4

参考资料:

1.《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》
2. 张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.

所用软件:vtk7.0+visual studio 2013

猜你喜欢

转载自blog.csdn.net/kateyabc/article/details/80914294