图像重采样后图像的维数会发生改变。当重采样图像小于原图像维数时,称为降采样;当重采样图像维数大于原图像时,称为升采样。VTK中可以方便的对图像进行重采样。vtkImageShrink3D类实现图像降采样。降采样需要设置每个方向的采样率,降采样率越大,图像越模糊。升采样的原理与降采样原理一致,只是增加采样点数来增加图像的维数。VTK中vtkImageMagnify来实现图像的升采样。
#include <vtkSmartPointer.h>
#include <vtkBMPReader.h>
#include <vtkImageData.h>
#include <vtkImageShrink3D.h> //降采样头文件
#include <vtkImageMagnify.h> //升采样头文件
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h> //交互样式
int main()
{
vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
reader->SetFileName("data\\lena.bmp");
reader->Update();
vtkSmartPointer<vtkImageShrink3D> shrinkFilter = vtkSmartPointer<vtkImageShrink3D>::New();
shrinkFilter->SetInputConnection(reader->GetOutputPort());//建立管道
shrinkFilter->SetShrinkFactors(16, 16, 1);//设置降采样率
shrinkFilter->Update();
vtkSmartPointer<vtkImageMagnify> magnifyFilter = vtkSmartPointer<vtkImageMagnify>::New();
magnifyFilter->SetInputConnection(reader->GetOutputPort());
magnifyFilter->SetMagnificationFactors(10, 10, 1);
magnifyFilter->Update();
int originalDims[3];
reader->GetOutput()->GetDimensions(originalDims);
double originalSpacing[3];
reader->GetOutput()->GetSpacing(originalSpacing);
int shrinkDims[3];
shrinkFilter->GetOutput()->GetDimensions(shrinkDims);
double shrinkSpacing[3];
shrinkFilter->GetOutput()->GetSpacing(shrinkSpacing);
int magnifyDims[3];
magnifyFilter->GetOutput()->GetDimensions(magnifyDims);
double magnifuSpacing[3];
magnifyFilter->GetOutput()->GetSpacing(magnifuSpacing);
std::cout << "原始维度: " << originalDims[0] << "*" << originalDims[1] << "*" << originalDims[2] << std::endl;
std::cout << "原始像素间距: " << originalSpacing[0] << " " << originalSpacing[1] << " " << originalSpacing[2] << std::endl;
std::cout << "降采样维度: " << shrinkDims[0] << "*" << shrinkDims[1] << "*" << shrinkDims[2] << std::endl;
std::cout << "降采样像素间距:" << shrinkSpacing[0] << " " << shrinkSpacing[1] << " " << shrinkSpacing[2] << std::endl;
std::cout << "升采样维度: " << magnifyDims[0] << "*" << magnifyDims[1] << "*" << magnifyDims[2] << std::endl;
std::cout << "升采样像素间距:" << magnifuSpacing[0] << " " << magnifuSpacing[1] << " " << magnifuSpacing[2] << std::endl;
vtkSmartPointer<vtkImageActor> origActor = vtkSmartPointer<vtkImageActor>::New();
origActor->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkImageActor> shrinkActor = vtkSmartPointer<vtkImageActor>::New();
shrinkActor->SetInputData(shrinkFilter->GetOutput());
vtkSmartPointer<vtkImageActor> magnifyActor = vtkSmartPointer<vtkImageActor>::New();
magnifyActor->SetInputData(magnifyFilter->GetOutput());
///////////////////////////////////////////////////////
double origView[4] = { 0, 0, 0.3, 1.0 };
double shrinkView[4] = { 0.3, 0, 0.6, 1.0 };
double magnifyView[4] = { 0.6, 0, 1, 1 };
vtkSmartPointer<vtkRenderer> origRender = vtkSmartPointer<vtkRenderer>::New();
origRender->SetViewport(origView);//视图
origRender->AddActor(origActor);//对象
origRender->ResetCamera();//相机
origRender->SetBackground(0, 0, 0);//背景
vtkSmartPointer<vtkRenderer> shrinkRender = vtkSmartPointer<vtkRenderer>::New();
shrinkRender->SetViewport(shrinkView);
shrinkRender->AddActor(shrinkActor);
shrinkRender->ResetCamera();
shrinkRender->SetBackground(0, 0, 0);
vtkSmartPointer<vtkRenderer> magnifyRender = vtkSmartPointer<vtkRenderer>::New();
magnifyRender->SetViewport(magnifyView);
magnifyRender->AddActor(magnifyActor);
magnifyRender->ResetCamera();
magnifyRender->SetBackground(0, 0, 0);
/////////////////////////////////////////////////
vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
rw->AddRenderer(origRender);
rw->AddRenderer(shrinkRender);
rw->AddRenderer(magnifyRender);
rw->SetSize(720, 240);
rw->SetWindowName("Image-Shrink-Magnify");
rw->Render();
////////////////////////////////////////////////
vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
rwi->SetInteractorStyle(style);
rwi->SetRenderWindow(rw);
rwi->Initialize();
rwi->Start();
return 0;
}
运行结果:
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.