Empty deformation field issue with missing or empty binary segmentation masks
Operating system and version
Ubuntu 22.04
CPU architecture
x86_64 (PC, Intel Mac, other Intel/AMD)
ANTs code version
ANTs Version: 2.6.2.post3-g193e36e Compiled: Jul 1 2025 00:54:20
ANTs installation type
Compiled from source
Summary of the problem
I ran into an issue while performing pairwise registration using segmentation masks. Specifically, I have a list of binary maps, each representing a different anatomical label. The problem occurs when one or more of these binary maps are empty, either because a structure wasn’t annotated in the segmentation or because the structure is missing due to temporal changes in the brain. When such empty maps are included, the registration using the MeanSquare metric terminates prematurely, producing an empty deformation field without reporting any explicit error. My issue is to find a way to handle missing temporal segmentations during the optimization process without completely excluding the affected structures from the registration task, or to determine whether my Python script that formats the shell command contains any errors.
Commands to reproduce the problem.
import os
import argparse
def main(path_source, path_target, path_source_binary_mask, path_target_binary_mask, label_range, gradientStep, transform, output_prefix):
# Construct the command
prefix = f'ants_{transform}_gs{gradientStep}'
prefix += '_seg_'
cmd = f'antsRegistration -d 3 -o {prefix} '
cmd += f'--transform {transform}[' + gradientStep + ',2,0] '
weighting_seg = 1.0 / len(label_range)
for label in label_range:
starting_lb_path = os.path.join(path_source_binary_mask, f'{label}.nii.gz')
current_lb_path = os.path.join(path_target_binary_mask, f'{label}.nii.gz')
cmd += f'--metric MeanSquares[{current_lb_path}, {starting_lb_path},{weighting_seg}] '
cmd += '--convergence [1000x500x500x500,1e-6,10] '
cmd += '--shrink-factors 8x4x2x1 '
cmd += '--smoothing-sigmas 3x2x1x0vox '
cmd += '--verbose 1'
print(cmd)
os.system(cmd)
# Apply the transformation
cmd = f'antsApplyTransforms -d 3 -r {path_target} -i {path_source} -t {prefix}0Warp.nii.gz -o {prefix}_{output_prefix}_Warped.nii.gz '
print(cmd)
os.system(cmd)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Test different ANTs parameters to capture folding')
parser.add_argument('-s', '--source_intensity', help='Source image', type=str)
parser.add_argument('-t', '--target_intensity', help='Target image', type=str)
parser.add_argument('-sb', '--source_binary_mask', help='Source folder with binary images (string)', type=str)
parser.add_argument('-tb', '--target_binary_mask', help='Target folder with binary images (string)', type=str)
parser.add_argument('-r', '--label_range', help='Label range (e.g. 0-19)', type=int, nargs='+', required=False, default=range(0, 19))
parser.add_argument('-g', '--gradient', help='Gradient step (string)', type=str, required=False, default='1')
parser.add_argument('-tf', '--transform', help='Transform type (string)', type=str, required=False, default='SyN')
parser.add_argument('-o', '--output_prefix', help='Output prefix (string)', type=str, required=False, default='ants_')
args = parser.parse_args()
main(path_source=args.source_intensity, path_target=args.target_intensity, path_source_binary_mask=args.source_binary_mask, path_target_binary_mask=args.target_binary_mask, gradientStep=args.gradient, label_range=args.label_range, transform=args.transform, output_prefix=args.output_prefix)
Output of the command with verbose output.
Data to reproduce the problem
Have you seen the function label_image_registration(...)? Example here.