Skip to content

ThinPlateSplineTransform

web-test/Cxx/PolyData/ThinPlateSplineTransform



Other languages

See (Java)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

ThinPlateSplineTransform.cxx

#include <vtkActor2D.h>
#include <vtkBMPReader.h>
#include <vtkDataObject.h>
#include <vtkImageBlend.h>
#include <vtkImageGridSource.h>
#include <vtkImageMapToColors.h>
#include <vtkImageMapper.h>
#include <vtkImageReslice.h>
#include <vtkInteractorStyleTerrain.h>
#include <vtkLookupTable.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkThinPlateSplineTransform.h>

#include <iostream>
#include <string>

// Warp an image with a thin plate spline.

int main(int argc, char* argv[])
{
  vtkNew<vtkNamedColors> colors;

  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " Filename.bmp e.g. masonry.bmp"
              << std::endl;
    return EXIT_FAILURE;
  }

  // First, create an image to warp.
  vtkNew<vtkImageGridSource> imageGrid;
  imageGrid->SetGridSpacing(16, 16, 0);
  imageGrid->SetGridOrigin(0, 0, 0);
  imageGrid->SetDataExtent(0, 255, 0, 255, 0, 0);
  imageGrid->SetDataScalarTypeToUnsignedChar();

  vtkNew<vtkLookupTable> table;
  table->SetTableRange(0, 1);
  table->SetAlphaRange(0.0, 1.0);
  table->SetHueRange(0.15, 0.15);
  table->SetSaturationRange(1, 1);
  table->SetValueRange(0, 1);
  table->Build();

  vtkNew<vtkImageMapToColors> alpha;
  alpha->SetInputConnection(imageGrid->GetOutputPort());
  alpha->SetLookupTable(table);

  vtkNew<vtkBMPReader> reader;
  reader->SetFileName(argv[1]);
  reader->Update();
  auto dataExtent = reader->GetDataExtent();
  // Use dataExtent[1] and dataExtent[3] to set the render window size.

  vtkNew<vtkImageBlend> blend;
  blend->AddInputConnection(0, reader->GetOutputPort());
  blend->AddInputConnection(0, alpha->GetOutputPort());

  // Next, create a ThinPlateSpline transform.

  vtkNew<vtkPoints> p1;
  p1->SetNumberOfPoints(8);
  p1->SetPoint(0, 0, 0, 0);
  p1->SetPoint(1, 0, 255, 0);
  p1->SetPoint(2, 255, 0, 0);
  p1->SetPoint(3, 255, 255, 0);
  p1->SetPoint(4, 96, 96, 0);
  p1->SetPoint(5, 96, 159, 0);
  p1->SetPoint(6, 159, 159, 0);
  p1->SetPoint(7, 159, 96, 0);

  vtkNew<vtkPoints> p2;
  p2->SetNumberOfPoints(8);
  p2->SetPoint(0, 0, 0, 0);
  p2->SetPoint(1, 0, 255, 0);
  p2->SetPoint(2, 255, 0, 0);
  p2->SetPoint(3, 255, 255, 0);
  p2->SetPoint(4, 96, 159, 0);
  p2->SetPoint(5, 159, 159, 0);
  p2->SetPoint(6, 159, 96, 0);
  p2->SetPoint(7, 96, 96, 0);

  vtkNew<vtkThinPlateSplineTransform> transform;
  transform->SetSourceLandmarks(p2);
  transform->SetTargetLandmarks(p1);
  transform->SetBasisToR2LogR();
  // You must invert the transform before passing it to vtkImageReslice.
  transform->Inverse();

  vtkNew<vtkImageReslice> reslice;
  reslice->SetInputConnection(blend->GetOutputPort());
  reslice->SetResliceTransform(transform);
  reslice->SetInterpolationModeToLinear();
  vtkNew<vtkImageMapper> map;
  map->SetInputConnection(reslice->GetOutputPort());
  map->SetColorWindow(255.0);
  map->SetColorLevel(127.5);
  map->SetZSlice(0);
  vtkNew<vtkActor2D> act;
  act->SetMapper(map);

  vtkNew<vtkRenderer> renderer;
  renderer->AddActor(act);
  renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());

  vtkNew<vtkRenderWindow> window;
  window->SetSize(dataExtent[1], dataExtent[3]);
  window->SetWindowName("ThinPlateSplineTransform");

  window->AddRenderer(renderer);
  vtkNew<vtkRenderWindowInteractor> interactor;
  interactor->SetRenderWindow(window);
  vtkNew<vtkInteractorStyleTerrain> style;
  interactor->SetInteractorStyle(style);
  window->Render();
  interactor->Initialize();
  interactor->Start();

  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(ThinPlateSplineTransform)

find_package(VTK COMPONENTS 
  CommonColor
  CommonCore
  CommonDataModel
  CommonTransforms
  IOImage
  ImagingCore
  ImagingSources
  InteractionStyle
  RenderingContextOpenGL2
  RenderingCore
  RenderingFreeType
  RenderingGL2PSOpenGL2
  RenderingOpenGL2
)

if (NOT VTK_FOUND)
  message(FATAL_ERROR "ThinPlateSplineTransform: Unable to find the VTK build folder.")
endif()

# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
add_executable(ThinPlateSplineTransform MACOSX_BUNDLE ThinPlateSplineTransform.cxx )
  target_link_libraries(ThinPlateSplineTransform PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
  TARGETS ThinPlateSplineTransform
  MODULES ${VTK_LIBRARIES}
)

Download and Build ThinPlateSplineTransform

Click here to download ThinPlateSplineTransform and its CMakeLists.txt file. Once the tarball ThinPlateSplineTransform.tar has been downloaded and extracted,

cd ThinPlateSplineTransform/build

If VTK is installed:

cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

make

and run it:

./ThinPlateSplineTransform

WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.