注:此文知识学习笔记,仅记录完整程序和实现结果,具体原理参见:
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 reader = vtkSmartPointer::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 imgViewer = vtkSmartPointer::New(); //图像显示,vtkImageViewer2中封装了vtk图像显示的管线
imgViewer->SetInputData(reader->GetOutput());//区别于imgViewer->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer rwi = vtkSmartPointer::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
#include
#include
#include
#include
#include
#include
#include
int main()
{
vtkSmartPointer reader = vtkSmartPointer::New();//读取bmp图像
reader->SetFileName("test.bmp");
reader->Update();
int subRegion[6] = { 31, 79, 14, 50, 0, 0 };
vtkImageIterator 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 imgViewer = vtkSmartPointer::New();
imgViewer->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer rwi = vtkSmartPointer::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.