1.VTK中的图像重采样实现
图像重采样是指对采样后形成的由离散数据组成的数字图像按所需的像元位置或像元问距重新采样,以构成几何变换后的新图像。重采样过程本质上是图像恢复过程,它用输入的离散数字图像重建代表原始图像二维连续函数,再按新的像元间距和像元位置进行采样。其数学过程是根据重建的连续函数(曲面),用周围若干像元点的值估计或内插出新采样点的值。图像重采样在图像处理中应用非常广泛,如SIFT特征提取。
图像重采样后图像的维数会发生改变。当重采样图像小于原图像维数时,称为降采样;当重采样图像维数大于原图像时,称为升采样。VTK中可以方便的对图像进行重采样。vtkImageShrink3D类实现图像降采样。降采样需要设置每个方向的采样率,降采样率越大,图像越模糊。升采样的原理与降采样原理一致,只是增加采样点数来增加图像的维数。VTK中vtkImageMagnify来实现图像的升采样。
实验代码如下所示:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
#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("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(1, 0, 0);
vtkSmartPointer<vtkRenderer> shrinkRender =
vtkSmartPointer<vtkRenderer>::New();
shrinkRender->SetViewport(shrinkView);
shrinkRender->AddActor(shrinkActor);
shrinkRender->ResetCamera();
shrinkRender->SetBackground(0, 1, 0);
vtkSmartPointer<vtkRenderer> magnifyRender =
vtkSmartPointer<vtkRenderer>::New();
magnifyRender->SetViewport(magnifyView);
magnifyRender->AddActor(magnifyActor);
magnifyRender->ResetCamera();
magnifyRender->SetBackground(0, 0, 1);
/////////////////////////////////////////////////
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设置相应的放大采样率。上
面例子中分别对原图像维数缩小原来的1/16和放大为原来的10倍,执行结果如下:
从图中可以看成,重采样图像已经变得十分模糊了。而升采样图像则变化不大。程序中输出了原图和重采样图像的维数和像素间隔,从输出来看,原图像的维数为512x512,缩小16倍后,图像维数变为32x32。需要注意的是,原图的像素间隔为(1,1,1),而重采样后像素间隔变为(16, 16, 1),这是因为采样是在世界坐标系下进行的,当采样图像的维数减小时,采样的像素间隔也相应的变大,这样保持图像的区域不会发生改变。同样的道理,当升采样后图像的维数变为原来的10倍,而像素间隔变为原来的十分之一。
另外,图像的重采样类有:vtkImageResample。
2.参看资料
1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3.《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》
4. 张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.