-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add high level function for rigid registration
- Loading branch information
Showing
4 changed files
with
104 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import numpy as np | ||
|
||
from scipy.optimize import minimize | ||
|
||
import pymirc.image_operations as pymi | ||
import pymirc.metrics.cost_functions as pymr | ||
|
||
def rigid_registration(vol_float, vol_fixed, aff_float, aff_fixed, | ||
downsample_facs = [4], metric = pymr.neg_mutual_information, | ||
opts = {'ftol':1e-2,'xtol':1e-2,'disp':True,'maxiter':20,'maxfev':5000}, | ||
method = 'Powell', metric_kwargs = {}): | ||
""" rigidly coregister a 3D floating volume to a fixed (reference) volume | ||
Parameters | ||
---------- | ||
vol_float : 3D numpy array | ||
the floating volume | ||
vol_fixed : 3D numpy array | ||
the fixed (reference) volume | ||
aff_float : 2D 4x4 numpy array | ||
affine transformation matrix that maps from pixel to world coordinates for floating volume | ||
aff_fixed : 2D 4x4 numpy array | ||
affine transformation matrix that maps from pixel to world coordinates for fixed volume | ||
downsample_facs : None of array_like | ||
perform registrations on downsampled grids before registering original volumes | ||
(multi-resolution approach) | ||
metric : function(x,y, **kwargs) | ||
metric that compares transformed floating and fixed volume | ||
metric_kwargs : dict | ||
keyword arguments passed to the metric function | ||
opts : dictionary | ||
passed to scipy.optimize.minimize as options | ||
method : string | ||
passed to scipy.optimize.minimize as method (which optimizer to use) | ||
Returns | ||
------- | ||
tuple of 3 | ||
- the transformed (coregistered) floating volume | ||
- the registration affine transformation matrix | ||
- the 6 registration parameters (3 translations, 3 rotations) from which the | ||
affine matrix was derived | ||
Note | ||
---- | ||
To apply the registration affine transformation use: | ||
new_vol = pymi.aff_transform(vol, reg_aff, vol_fixed.shape, cval = vol.min()) | ||
""" | ||
# define the affine transformation that maps the floating to the fixed voxel grid | ||
# we need this to avoid the additional interpolation in case the voxel sizes are not the same | ||
pre_affine = np.linalg.inv(aff_float) @ aff_fixed | ||
|
||
reg_params = np.zeros(6) | ||
|
||
# (1) initial registration with downsampled arrays | ||
if downsample_facs is not None: | ||
for dsf in downsample_facs: | ||
ds_aff = np.diag([dsf,dsf,dsf,1.]) | ||
|
||
# down sample fixed volume | ||
vol_fixed_ds = pymi.aff_transform(vol_fixed, ds_aff, | ||
np.ceil(np.array(vol_fixed.shape)/dsf).astype(int)) | ||
|
||
res = minimize(pymr.regis_cost_func, reg_params, method = method, options = opts, | ||
args = (vol_fixed_ds, vol_float, True, True, metric, pre_affine @ ds_aff, | ||
metric_kwargs)) | ||
|
||
reg_params = res.x.copy() | ||
# we have to scale the translations by the down sample factor since they are in voxels | ||
reg_params[:3] *= dsf | ||
|
||
|
||
# (2) registration with full arrays | ||
res = minimize(pymr.regis_cost_func, reg_params, method = method, options = opts, | ||
args = (vol_fixed, vol_float, True, True, metric, pre_affine, | ||
metric_kwargs)) | ||
reg_params = res.x.copy() | ||
|
||
|
||
# define the final affine transformation that maps from the PET grid to the rotated CT grid | ||
reg_aff = pre_affine @ pymi.kul_aff(reg_params, origin = np.array(vol_fixed.shape)/2) | ||
|
||
# transform the floating volume | ||
vol_float_coreg = pymi.aff_transform(vol_float, reg_aff, vol_fixed.shape, cval = vol_float.min()) | ||
|
||
return vol_float_coreg, reg_aff, reg_params |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters