MIR¶
Deformable registration, from research to results
MIR brings state-of-the-art registration networks, classical baselines, training losses,
evaluation metrics and reproducible benchmark pipelines together behind one simple interface:
a (moving, fixed) pair in, a dense displacement field out.
A LUMIR brain MRI pair registered with TransMorph-TVF: moving, fixed and warped images, the deformation and its log Jacobian determinant (folding in 0.003% of voxels).
Why MIR¶
Every model takes (moving, fixed) and returns a voxel displacement that one
SpatialTransformer applies to images and label maps. Swapping architectures is a one-line change.
TransMorph, VFA, SITReg, VoxelMorph, LessNet, Fourier-Net, hypernetwork variants, and the classical ConvexAdam, deedsBCV and FireANTs, all callable the same way.
Choose the transformation model: displacement, stationary or time-varying velocity fields, symmetric inverse-consistent mappings, or LDDMM geodesic shooting.
Learn where the deformation should be smooth and where it may be sharp, with Beta priors, hypernetwork-conditioned strength, or weighted metrics. Try it live in the browser playground.
NCC, SSIM, MIND, mutual information, correlation ratio and Dice losses; diffusion, local and GradICON regularizers; Jacobian-based folding metrics; contrast augmentation.
Weights for brain MRI (LUMIR, IXI) and PET/CT (autoPET), and end-to-end tutorials that reproduce Learn2Reg and IXI benchmarks.
A first look¶
import torch, nibabel as nib
from MIR import ModelWeights
from MIR.models import VFA, SpatialTransformer
import MIR.models.configs_VFA as configs_VFA
load = lambda p: torch.from_numpy(nib.load(p).get_fdata()[None, None]).float().cuda()
mov, fix = load('subject.nii.gz'), load('template.nii.gz')
config = configs_VFA.get_VFA_default_config()
config.img_size = fix.shape[2:]
model = VFA(config, device='cuda:0').cuda().eval()
key = ModelWeights['VFA-LUMIR24-MonoModal']['wts_key']
model.load_state_dict(torch.load('VFA_LUMIR24.pth')[key])
with torch.no_grad():
flow = model((mov, fix)) # [1, 3, D, H, W], in voxels
warped = SpatialTransformer(fix.shape[2:]).cuda()(mov, flow)
from MIR.models import TransMorph, SpatialTransformer
from MIR.image_similarity import NCC_vxm
from MIR.deformation_regularizer import Grad3d
import MIR.models.configs_TransMorph as configs_TransMorph
config = configs_TransMorph.get_3DTransMorph3Lvl_config()
config.img_size = (160, 192, 224)
model = TransMorph(config, SVF=True).cuda() # diffeomorphic (SVF)
warp = SpatialTransformer(config.img_size).cuda()
similarity, smoothness = NCC_vxm(), Grad3d(penalty='l2')
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
for mov, fix in loader: # unsupervised: no labels needed
mov, fix = mov.cuda(), fix.cuda()
flow = model((mov, fix))
loss = similarity(warp(mov, flow), fix) + 1.0 * smoothness(flow, fix)
optimizer.zero_grad(); loss.backward(); optimizer.step()
from MIR.models import SpatialTransformer
from MIR.accuracy_measures import dice_val_VOI, calc_jac_dets, get_identity_grid, calc_measurements
warp_labels = SpatialTransformer(fix.shape[2:], mode='nearest').cuda()
dice = dice_val_VOI(warp_labels(mov_seg, flow).long(), fix_seg.long(), num_clus=n_labels)
disp = flow[0].cpu().numpy() # folding metrics
jac = calc_jac_dets(disp + get_identity_grid(disp))
n_folded, _, folded_volume, _ = calc_measurements(jac, mask)
Explore the documentation¶
Install MIR, run a pretrained model, benchmark on IXI, build a template.
Conventions, transformation models, regularization, losses and metrics, training recipes.
Every model family with variants, usage, pretrained weights and references.
Runnable training and evaluation pipelines for LUMIR, IXI, autoPET and atlas building.
Auto-generated reference of every module, class and function.
The papers implemented in MIR and how to cite them.
Citing MIR¶
If MIR is useful in your work, please cite the paper of the model you used (listed on each model page and under Publications) and link to the repository.