Main Content

Register Multimodal Medical Image Volumes with Spatial Referencing

This example shows how to align two medical image volumes using moment-of-mass-based registration.

Multimodal image registration aligns images acquired using different imaging modalities, such as MRI and CT. Even when acquired for the same patient and region of interest, multimodal images can be misaligned due to differences in patient positioning (translation or rotation) and voxel size (scaling). Different imaging modalities often have different voxel sizes due to scanner variability and concerns about scan time and radiation dose. The imregmoment function enables fast registration of 3-D image volumes, including multimodal images.

Medical images have an intrinsic coordinate system defined by rows, columns, and slices and a patient coordinate system that describes the real-world position and voxel spacing. You can use the medicalVolume object to import and manage the spatial referencing of a medical image volume. To register images with different voxel sizes using imregmoment, you must use spatial referencing to register the images in the patient coordinate system. During registration, imregmoment aligns a moving image with a fixed image, and then resamples the aligned image in the intrinsic coordinates of the fixed image. The registered volumes share one patient coordinate system and have the same number of rows, columns, and slices.

In this example, you use medicalVolume and imregmoment to register multimodal MRI and CT images of the head.

Load Images

The data used in this example is a modified version of the 3-D CT and MRI data sets from The Retrospective Image Registration Evaluation (RIRE) Dataset, provided by Dr. Michael Fitzpatrick. For more information, see the RIRE Project homepage. The modified data set contains one CT scan and one MRI scan stored in the NRRD file format. The size of the entire data set is approximately 35 MB. Download the data set from the MathWorks® website, then unzip the folder.

zipFile = matlab.internal.examples.downloadSupportFile("medical", ...
    "MedicalRegistrationNRRDdata.zip");
filepath = fileparts(zipFile);
unzip(zipFile,filepath)

In image registration, consider one image to be the fixed image and the other image to be the moving image. The goal of registration is to align the moving image with the fixed image. In this example, the fixed image is a T1 weighted MRI image. The moving image is a CT image from the same patient. The images are stored in the NRRD file format.

Use medicalVolume to read the MRI image. By looking at the Voxels and VoxelSpacing properties, you can determine that the MRI volume is a 256-by-256-by-26 voxel array, where each voxel is 1.25-by-1.25-by-4.0 mm.

filenameMRI = fullfile(filepath,"supportfilesNRRD","Patient007MRT1.nrrd");
fixedMRIVolume = medicalVolume(filenameMRI)
fixedMRIVolume = 
  medicalVolume with properties:

                 Voxels: [256×256×26 single]
         VolumeGeometry: [1×1 medicalref3d]
           SpatialUnits: "unknown"
            Orientation: "unknown"
           VoxelSpacing: [1.2500 1.2500 4]
           NormalVector: [0 0 1]
       NumCoronalSlices: []
      NumSagittalSlices: []
    NumTransverseSlices: []
           PlaneMapping: ["unknown"    "unknown"    "unknown"]
               Modality: "unknown"
          WindowCenters: []
           WindowWidths: []

Import the CT image. The size of each voxel in the CT image is 0.65-by-0.65-by-4 mm, which is smaller than in the MRI image.

filenameCT = fullfile(filepath,"supportfilesNRRD","Patient007CT.nrrd");
movingCTVolume = medicalVolume(filenameCT)
movingCTVolume = 
  medicalVolume with properties:

                 Voxels: [512×512×28 single]
         VolumeGeometry: [1×1 medicalref3d]
           SpatialUnits: "unknown"
            Orientation: "unknown"
           VoxelSpacing: [0.6536 0.6536 4]
           NormalVector: [0 0 1]
       NumCoronalSlices: []
      NumSagittalSlices: []
    NumTransverseSlices: []
           PlaneMapping: ["unknown"    "unknown"    "unknown"]
               Modality: "unknown"
          WindowCenters: []
           WindowWidths: []

Extract the image voxel data from the Voxels property of the medicalVolume objects.

fixedMRIVoxels = fixedMRIVolume.Voxels;
movingCTVoxels = movingCTVolume.Voxels;

Display Unregistered Images

Use the imshowpair function to judge image alignment. First, calculate the location of the middle slice of each volume. The VolumeGeometry property of the medical volume object contains a medicalref3d object, which specifies spatial details about the volume. Use the VolumeSize property of each medicalref3d object to calculate the location of the middle slice of the corresponding volume, in voxels.

fixedVolumeSize = fixedMRIVolume.VolumeGeometry.VolumeSize;
movingVolumeSize = movingCTVolume.VolumeGeometry.VolumeSize;

centerFixed = fixedVolumeSize/2;
centerMoving = movingVolumeSize/2;

Define spatial referencing for the 2-D slices using imref2d. Specify the size, in voxels, and voxel spacing, in millimeters, of the transverse slices.

fixedVoxelSpacing = fixedMRIVolume.VoxelSpacing;
movingVoxelSpacing = movingCTVolume.VoxelSpacing;

Rfixed2D = imref2d(fixedVolumeSize(1:2),fixedVoxelSpacing(2),fixedVoxelSpacing(1));
Rmoving2D = imref2d(movingVolumeSize(1:2),movingVoxelSpacing(2),movingVoxelSpacing(1)); 

Display the image slices in the patient coordinate system using imshowpair. Plot the slice in the third spatial dimension, which corresponds to the transverse anatomical plane. The MRI slice is magenta, and the CT slice is green.

figure
imshowpair(movingCTVoxels(:,:,centerMoving(3)), ...
   Rmoving2D, ...
   fixedMRIVoxels(:,:,centerFixed(3)), ...
   Rfixed2D)
title("Unregistered Transverse Slice")

You can also display the volumes as 3-D objects. Create a viewer3d object, in which you can display multiple volumes.

viewerUnregistered = viewer3d(BackgroundColor="black",BackgroundGradient="off");

Display the medicalVolume objects as 3-D isosurfaces using volshow. The volshow function uses medicalVolume properties to display each volume in its respective patient coordinate system.

volshow(fixedMRIVolume, ...
    Parent=viewerUnregistered, ...
    RenderingStyle="Isosurface", ...
    IsosurfaceValue=0.05, ...
    Colormap=[1 0 1], ...
    Alphamap=1);
Warning: The volume's VolumeGeometry.PatientCoordinateSystem property is not set. Assuming "LPS+" for visualization.
volshow(movingCTVolume, ...
    Parent=viewerUnregistered, ...
    RenderingStyle="Isosurface", ...
    IsosurfaceValue=0.05, ...
    Colormap=[0 1 0], ...
    Alphamap=1);
Warning: The volume's VolumeGeometry.PatientCoordinateSystem property is not set. Assuming "LPS+" for visualization.

Register Images

To accurately register volumes with different voxel dimensions, specify the spatial referencing for each volume using imref3d objects. Create each imref3d object using the volume size in voxels and the voxel dimensions in millimeters.

Rfixed3d  = imref3d(fixedVolumeSize,fixedVoxelSpacing(2), ...
    fixedVoxelSpacing(1),fixedVoxelSpacing(3));
Rmoving3d = imref3d(movingVolumeSize,movingVoxelSpacing(2), ...
    movingVoxelSpacing(1),movingVoxelSpacing(3));

The imregmoment function sets fill pixels added to the registered volume to 0. To improve the display of registration results, scale the CT intensities to the range [0, 1], so that the fill value is equal to the minimum of the image data range.

rescaledMovingCTVoxels = rescale(movingCTVoxels);

Register the volumes using imregmoment, including the imref3d objects as inputs. Specify the MedianThresholdBitmap name-value argument as true, which is appropriate for multimodal images.

[geomtform,movingCTRegisteredVoxels] = imregmoment(rescaledMovingCTVoxels,Rmoving3d, ...
    fixedMRIVoxels,Rfixed3d,MedianThresholdBitmap=true);

The geomtform output is an affinetform3d geometric transformation object. The T property of geomtform contains the 3-D affine transformation matrix that maps the moving CT volume in its patient coordinate system to the fixed MRI volume in its patient coordinate system.

geomtform.T
ans = 4×4

    1.0000   -0.0039    0.0013         0
    0.0039    1.0000    0.0063         0
   -0.0014   -0.0063    1.0000         0
   -4.8094  -16.0063   -1.3481    1.0000

The movingRegisteredVoxels output contains the registered CT volume. The imregmoment function resamples the aligned CT volume in the MRI intrinsic coordinates, so the registered volumes have the same number of rows, columns, and slices.

whos movingCTRegisteredVoxels fixedMRIVoxels
  Name                            Size                  Bytes  Class     Attributes

  fixedMRIVoxels                256x256x26            6815744  single              
  movingCTRegisteredVoxels      256x256x26            6815744  single              

Create medicalVolume Object for Registered Image

Create a new medicalVolume object that contains the registered voxel data and its spatial referencing information. You can create a medicalVolume object by specifying a voxel array and a medicalref3d object. The registered CT volume has the same spatial referencing as the original MRI volume, so use the medicalref3d object stored in the VolumeGeometry property of fixedMRIVolume.

R = fixedMRIVolume.VolumeGeometry;
movingRegisteredVolume = medicalVolume(movingCTRegisteredVoxels,R)
movingRegisteredVolume = 
  medicalVolume with properties:

                 Voxels: [256×256×26 single]
         VolumeGeometry: [1×1 medicalref3d]
           SpatialUnits: "unknown"
            Orientation: "unknown"
           VoxelSpacing: [1.2500 1.2500 4]
           NormalVector: [0 0 1]
       NumCoronalSlices: []
      NumSagittalSlices: []
    NumTransverseSlices: []
           PlaneMapping: ["unknown"    "unknown"    "unknown"]
               Modality: "unknown"
          WindowCenters: []
           WindowWidths: []

Display Registered Images

To check the registration results, use imshowpair to view the middle transverse slices of the fixed and registered volumes. Use the spatial referencing object for the fixed volume.

figure
imshowpair(movingRegisteredVolume.Voxels(:,:,centerFixed(3)), ...
    Rfixed2D,fixedMRIVoxels(:,:,centerFixed(3)),Rfixed2D)
title("Registered Transverse Slice")

Display the registered volumes as 3-D isosurfaces using volshow. You can zoom and rotate the display to assess the registration results.

viewerRegistered = viewer3d(BackgroundColor="black",BackgroundGradient="off");
volshow(fixedMRIVolume, ...
    Parent=viewerRegistered, ...
    RenderingStyle="Isosurface", ...
    IsosurfaceValue=0.05, ...
    Colormap=[1 0 1], ...
    Alphamap=1);
Warning: The volume's VolumeGeometry.PatientCoordinateSystem property is not set. Assuming "LPS+" for visualization.
volshow(movingRegisteredVolume, ...
    Parent=viewerRegistered, ...
    RenderingStyle="Isosurface", ...
    IsosurfaceValue=0.05, ...
    Colormap=[0 1 0], ...
    Alphamap=1);
Warning: The volume's VolumeGeometry.PatientCoordinateSystem property is not set. Assuming "LPS+" for visualization.

See Also

| |

Related Topics