1、官方示例
来自官方示例代码,自己只是添加了理解。
代码:
#include <vtkCamera.h>
#include <vtkImageActor.h>
#include <vtkImageConstantPad.h>
#include <vtkImageMapToWindowLevelColors.h>
#include <vtkImageMapper3D.h>
#include <vtkImageMirrorPad.h>
#include <vtkImageProperty.h>
#include <vtkImageReader2.h>
#include <vtkImageReader2Factory.h>
#include <vtkInteractorStyleImage.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
int main(int argc, char* argv[])
{
vtkNew<vtkNamedColors> colors;
// Verify input arguments
if (argc < 2)
{
std::cout << "Usage: " << argv[0] << " Filename e.g. FullHead.mhd"
<< std::endl;
return EXIT_FAILURE;
}
// Read the image
vtkNew<vtkImageReader2Factory> readerFactory;
vtkSmartPointer<vtkImageReader2> reader;
reader.TakeReference(readerFactory->CreateImageReader2(argv[1]));
reader->SetFileName(argv[1]);
reader->Update();
// Pipelines
vtkNew<vtkImageConstantPad> constantPad;
constantPad->SetInputConnection(reader->GetOutputPort());
constantPad->SetConstant(800);
constantPad->SetOutputWholeExtent(-127, 383, -127, 383, 22, 22);
vtkNew<vtkImageMirrorPad> mirrorPad;
mirrorPad->SetInputConnection(reader->GetOutputPort());
mirrorPad->SetOutputWholeExtent(constantPad->GetOutputWholeExtent());
// Create actors
vtkNew<vtkImageMapToWindowLevelColors> constantPadColor;
constantPadColor->SetWindow(2000);
constantPadColor->SetLevel(1000);
constantPadColor->SetInputConnection(constantPad->GetOutputPort());
vtkNew<vtkImageActor> constantPadActor;
constantPadActor->GetMapper()->SetInputConnection(
constantPadColor->GetOutputPort());
constantPadActor->GetProperty()->SetInterpolationTypeToNearest();
vtkNew<vtkImageMapToWindowLevelColors> mirrorPadColor;
mirrorPadColor->SetWindow(2000);
mirrorPadColor->SetLevel(1000);
mirrorPadColor->SetInputConnection(mirrorPad->GetOutputPort());
vtkNew<vtkImageActor> mirrorPadActor;
mirrorPadActor->GetMapper()->SetInputConnection(
mirrorPadColor->GetOutputPort());
mirrorPadActor->GetProperty()->SetInterpolationTypeToNearest();
// Setup renderers
vtkNew<vtkRenderer> constantPadRenderer;
constantPadRenderer->SetViewport(0.0, 0.0, 0.5, 1.0);
constantPadRenderer->AddActor(constantPadActor);
constantPadRenderer->ResetCamera();
constantPadRenderer->SetBackground(colors->GetColor3d("SlateGray").GetData());
vtkNew<vtkRenderer> mirrorPadRenderer;
mirrorPadRenderer->SetViewport(0.5, 0.0, 1.0, 1.0);
mirrorPadRenderer->AddActor(mirrorPadActor);
mirrorPadRenderer->SetActiveCamera(constantPadRenderer->GetActiveCamera());
mirrorPadRenderer->SetBackground(
colors->GetColor3d("LightSlateGray").GetData());
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->SetSize(600, 300);
renderWindow->SetWindowName("Pad");
renderWindow->AddRenderer(constantPadRenderer);
renderWindow->AddRenderer(mirrorPadRenderer);
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
vtkNew<vtkInteractorStyleImage> style;
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
constantPadRenderer->GetActiveCamera()->Dolly(1.2);
constantPadRenderer->ResetCameraClippingRange();
renderWindow->Render();
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
输入图像:FullHead.mhd
执行结果:
解释: 程序中执行了2个pad操作,分别为 常数pad操作和镜像pad操作,分别如上图左右所示。
vtkNew<vtkImageConstantPad> constantPad;
constantPad->SetInputConnection(reader->GetOutputPort());
constantPad->SetConstant(800);
constantPad->SetOutputWholeExtent(-127, 383, -127, 383, 22, 22);
以左图结果为例, constantPad 按照extent从原图取图像,x和y的范围正负方向分别向外扩展了127,z轴只取了第22层的一层数据。
参考:Pad
2、其他例子
#include <vtkCamera.h>
#include <vtkImageActor.h>
#include <vtkImageConstantPad.h>
#include <vtkImageMapToWindowLevelColors.h>
#include <vtkImageMapper3D.h>
#include <vtkImageMirrorPad.h>
#include <vtkImageProperty.h>
#include <vtkImageReader2.h>
#include <vtkImageReader2Factory.h>
#include <vtkInteractorStyleImage.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkNIFTIImageReader.h>
#include <vtkNIFTIImageWriter.h>
#include <vtkImageData.h>
#include <vtkMatrix3x3.h>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
vtkNew<vtkNamedColors> colors;
// Verify input arguments
/* if (argc < 2)
{
std::cout << "Usage: " << argv[0] << " Filename e.g. FullHead.mhd"
<< std::endl;
return EXIT_FAILURE;
}*/
string fileName = "input.nii.gz";
vtkSmartPointer<vtkImageData> input;
vtkSmartPointer <vtkNIFTIImageReader> niftireader = vtkSmartPointer<vtkNIFTIImageReader>::New();
niftireader->SetFileName(fileName.c_str());
niftireader->Update();
input = niftireader->GetOutput();
int inputDims[3] = { 0 };
int extent[6] = { 0 };
double origin[3] = { 0 };
double spacing[3] = { 0 };
input->GetDimensions(inputDims);
input->GetExtent(extent);
input->GetOrigin(origin);
input->GetSpacing(spacing);
auto matrix = input->GetDirectionMatrix();
matrix->Print(std::cout);
matrix->SetElement(0, 0, -1);
matrix->SetElement(1, 1, -1);
matrix->Print(std::cout);
vtkNew<vtkImageConstantPad> constantPad;
constantPad->SetInputConnection(niftireader->GetOutputPort());
constantPad->SetConstant(800);
constantPad->SetOutputWholeExtent(0, 100, 40, 88, 100, 200);
constantPad->Update();
input->GetDirectionMatrix()->Print(std::cout);
vtkImageData* extracted = constantPad->GetOutput();
double newOrigin[3];
//newOrigin[0] = origin[0] + 127 * spacing[0];
newOrigin[1] = origin[1] + 40 * spacing[1];
newOrigin[2] = origin[2] + 100 * spacing[2];
extracted->SetOrigin(newOrigin);
extracted->SetDirectionMatrix(matrix);
string dstfileName = "constantPad.nii.gz";
vtkSmartPointer<vtkNIFTIImageWriter> envImageWriter = vtkSmartPointer<vtkNIFTIImageWriter>::New();
envImageWriter->SetInputData(extracted);
envImageWriter->SetFileName(dstfileName.c_str());
envImageWriter->Write();
return EXIT_SUCCESS;
}
输入图像:
输出图像:
二者显示在一起:
可以看到输入图像和输出图像是不对齐的,并且二者的方向也不一致。
当给输出图像增加一个变换,使其IJK to RAS 矩阵也为-1,-1,1时,如下图所示:
可以看到二者是对齐的。
并且发现下面这段代码对于方向并不起作用,可能需要其他设置才可以指定IJK to RAS 矩阵。为-1,-1,1
extracted->SetDirectionMatrix(matrix);
总结
通过这个示例说明使用vtkImageConstantPad 可以实现图像的基于体素的裁剪。但是需要注意方向和原点,避免数据对不齐。