5.3.2 VTK图像基本操作(图像像素值的访问与修改)

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

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

1、直接访问图像像素(索引法)

#include"vtkSmartPointer.h"
#include"vtkImageData.h"
#include"vtkBMPReader.h"
#include"vtkImageViewer2.h"
#include"vtkRenderer.h"
#include"vtkRenderWindow.h"
#include"vtkRenderWindowInteractor.h"
int main(){
	vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();  //读取图像
	reader->SetFileName("test.bmp");
	reader->Update();

	int dims[3];
	reader->GetOutput()->GetDimensions(dims);   
	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 < 79 && i>31 && j>14 && j < 50){
					unsigned char *pixel = (unsigned char*)(reader->GetOutput()->GetScalarPointer(i, j, k));
					*pixel = 255 - *pixel;  //将选择的区域设置成反色
					*(pixel + 1) = 255 - *(pixel + 1);
					*(pixel + 2) = 255 - *(pixel + 2);
				}
		   }
		}
	}
	vtkSmartPointer<vtkImageViewer2> imgViewer = vtkSmartPointer<vtkImageViewer2>::New(); //图像显示,vtkImageViewer2中封装了vtk图像显示的管线
	imgViewer->SetInputData(reader->GetOutput());//区别于imgViewer->SetInputConnection(reader->GetOutputPort()); 
	vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	imgViewer->SetupInteractor(rwi);
	imgViewer->Render();
	imgViewer->GetRenderer()->ResetCamera();//设置相机
	imgViewer->Render();
	imgViewer->GetRenderer()->SetBackground(1,1,1);//设置背景
	imgViewer->SetSize(640, 480);
	imgViewer->GetRenderWindow()->SetWindowName("VisitImagePixelDirectly");//窗口名称
	rwi->Start();
	
	return EXIT_SUCCESS;
} 

运行结果:

    

第二幅图像是将代码改为:

unsigned char *pixel = (unsigned char*)(reader->GetOutput()->GetScalarPointer(i, j, k));//GetScalarPointer获取访问图像像素值
					//GetScalarPointer()函数返回的是void*类型,因此需要根据图像的实际类型进行强制转换
					*pixel = 255 - *pixel;  //将选择的区域设置成反色
				/*	*(pixel + 1) = 255 - *(pixel + 1);
					*(pixel + 2) = 255 - *(pixel + 2);*/

在这里,我们需要注意的一点是VTK中彩色图以及矢量图的存储方式,具体如下:


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

2、迭代器方法访问图像像素

/***********************************************************/
//迭代器方法访问图像像素 vtkImageIterator类(此类是一个模板类,使用时,需要提供迭代的图像像素类型以及迭代的区域大小)
#include <vtkSmartPointer.h>  
#include <vtkBMPReader.h>  
#include <vtkImageData.h>  
#include <vtkImageIterator.h>  
#include <vtkImageViewer2.h>  
#include <vtkRenderer.h>  
#include <vtkRenderWindow.h>  
#include <vtkRenderWindowInteractor.h>  

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

	int subRegion[6] = { 31, 79, 14, 50, 0, 0 };
	vtkImageIterator<unsigned char> iter(reader->GetOutput(), subRegion);//定义一个子区域,iter的两个参数(一个是要访问的图像,另外一个是访问的图像区域)

	while (!iter.IsAtEnd())
	{
		unsigned char *inSI = iter.BeginSpan();   //组分迭代时,inSI = it.BeginSpan()获取第一个组分
		unsigned char *inSIEnd = iter.EndSpan();  // 表示组分迭代完毕

		while (inSI != inSIEnd)    //这个循环判断的是当前像素的组分是否迭代完毕,组分就是RGB三组,不同图像组分不一样
		{                         
			*inSI = 255 - *inSI;   //像素值取反
			++inSI;    //不断迭代组分
		}
		iter.NextSpan();
	}

	vtkSmartPointer<vtkImageViewer2> imgViewer = vtkSmartPointer<vtkImageViewer2>::New();
	imgViewer->SetInputConnection(reader->GetOutputPort());

	vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	imgViewer->SetupInteractor(rwi);
	imgViewer->Render();
	imgViewer->GetRenderer()->ResetCamera();
	imgViewer->Render();
	imgViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
	imgViewer->SetSize(640, 480);
	imgViewer->GetRenderWindow()->SetWindowName("VisitImagePixelIteratively");

	rwi->Start();

	return 0;
}
运行结果:


参考资料:

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

猜你喜欢

转载自blog.csdn.net/kateyabc/article/details/80587350
今日推荐