[Solved] BSplineTransformation from displacement vectors

I have pairs of points that describes the displacement between one image to another image. How can I use these points to construct a BSplineTransform?

An example of these points

[0 0] -> [18.53 57.52 ]
[76  0] -> [90.70 58.47 ]
[152   0] -> [162.26  60.35]
[228   0] -> [234.22  60.67]
[304   0] -> [305.71  61.47]

Hello @Flemingjp,

The relevant class is LandmarkBasedTransformInitializerFilter. This discussion is possibly also of interest.

1 Like

@zivy

Thank you. What isn’t clear here is how to create the landmarks from my currents points

fixed_points = [[0, 0], [0, 1]]

landmark_tx = sitk.LandmarkBasedTransformInitializerFilter()
landmark_tx.SetFixedLandmarks(fixed_points)

This results in the error

TypeError: in method 'LandmarkBasedTransformInitializerFilter_SetFixedLandmarks', argument 2 of type 'std::vector< double,std::allocator< double > > const &'

Hello @Flemingjp,

The LandmarkBasedTransformInitializer expects the point coordinates in a flat list [x1, y1, x2, y2,…]:

fixed_points_flat = [c for p in fixed_points for c in p]
1 Like

@zivy
Thank you for your help. This is my current issue

landmark_tx = sitk.LandmarkBasedTransformInitializer(
        transform = sitk.BSplineTransform(2),
        fixedLandmarks = fixed,
        movingLandmarks = moving,
        referenceImage = img,
        numberOfControlPoints = 4
    )
RuntimeError: Exception thrown in SimpleITK LandmarkBasedTransformInitializer: D:\a\1\sitk-build\ITK\Modules\Core\Common\src\itkPlatformMultiThreader.cxx:238:
ITK ERROR: PlatformMultiThreader(000002203ADDE880): Exception occurred during SingleMethodExecute
d:\a\1\sitk-build\itk-prefix\include\itk-5.2\itkBSplineScatteredDataPointSetToImageFilter.hxx:508:
ITK ERROR: BSplineScatteredDataPointSetToImageFilter(000002203AB10440): The reparameterized point component 1.07741 is outside the corresponding parametric domain of [0, 1).

To update - the issue was using the incorrect image size compared to the landmark points. The landmark points were beyond the image boundary.

Here is my complete solution

import numpy as np
import SimpleITK as sitk

# Flatten (n, 2) array of points
fixed = np.array(fixed_points).flatten().astype(float)
moving = np.array(moving_points).flatten().astype(float)

# Create landmark transform
landmark_tx = sitk.LandmarkBasedTransformInitializer(
        transform = sitk.BSplineTransform(2),   # Dimension=2 (2D Image)
        fixedLandmarks = fixed,
        movingLandmarks = moving,
        referenceImage = img,
        numberOfControlPoints = 4
    )

# Apply transform to image
rimg = sitk.Resample(img, landmark_tx)
1 Like