如何解决MONAI中ITK N4BiasCorrectionFilter的输入未设置错误?
解决ITK N4BiasFieldCorrectionFilter输入未设置的错误
问题描述
我尝试在MONAI U-Net的预处理环节中使用ITK N4BiasCorrectionFilter,编写了自定义N4ITKTransform类,相关加载与转换代码如下:
class N4ITKTransform(Transform): def __call__(self,image): filtered = [] for channel in image["image"]: # 从NumPy数组创建ITK图像 inputImage = itk.image_from_array(channel) # 创建偏置场校正过滤器 corrector = itk.N4BiasFieldCorrectionImageFilter() #corrector.SetInput(inputImage) # 执行过滤器 outputImage = corrector.Execute(inputImage) # 从ITK图像创建NumPy数组 filtered.append(itk.array_from_image(outputImage)) image["image"] = np.stack(filtered) return image monai_load = [ LoadImaged(keys=["image","segmentation"],image_only=False,reader=PILReader()), EnsureTyped(keys=["image", "segmentation"], data_type="numpy"), AddChanneld(keys=["segmentation","image"]), #RepeatChanneld(keys=["segmentation"],repeats=2), RepeatChanneld(keys=["image"],repeats=3), AsChannelFirstd(keys=["image"], channel_dim = 0), ] monai_transforms =[ AsDiscreted(keys=["segmentation"],threshold=0.5), ToTensord(keys=["image","segmentation"]), ] train_transforms = Compose(monai_load + [N4ITKTransform()] + monai_transforms)
在验证数据集上应用这些转换时:
check_ds = Dataset(data=train_data, transform=train_transforms) orig_ds = Dataset(data=train_data, transform=Compose(monai_load)) check_loader = DataLoader(check_ds, batch_size=1) orig_loader = DataLoader(orig_ds, batch_size=1) check_data = utils.first(check_loader) orig_data = utils.first(orig_loader)
运行后出现错误:
RuntimeError: C:\P\IPP\ITK-source\ITK\Modules\Core\Common\src\itkProcessObject.cxx:1339: ITK ERROR: N4BiasFieldCorrectionImageFilter(0000019BDBD62A40): Input Primary is required but not set. RuntimeError: applying transform <__main__.N4ITKTransform object at 0x0000019BF0CB5220> RuntimeError: applying transform <monai.transforms.compose.Compose object at 0x0000019BF0CB52E0>
解决方案
错误核心是ITK的N4BiasFieldCorrectionImageFilter在Python接口中未被正确初始化输入,同时该过滤器还依赖掩码图像和特定数据类型,具体修复步骤如下:
1. 修正ITK过滤器的调用逻辑
ITK Python绑定中,N4BiasFieldCorrectionImageFilter不能直接通过Execute(inputImage)传递输入,推荐使用更简洁的函数式接口,或标准的面向对象初始化方式:
- 函数式接口:直接调用
itk.n4_bias_field_correction传入图像和掩码 - 面向对象接口:通过
SetInput()设置输入、SetMaskImage()设置掩码,再调用Update()执行处理
2. 添加必要的掩码图像
N4校正需要掩码指定处理区域,若没有现成掩码,可创建与输入图像尺寸一致的全1掩码(表示处理整个图像)。
3. 确保图像为浮点型
ITK的N4过滤器要求输入图像为浮点型(如float32),需提前转换数据类型。
修改后的完整N4ITKTransform类
class N4ITKTransform(Transform): def __call__(self, image): filtered = [] for channel in image["image"]: # 将通道数据转换为float32,满足ITK N4的类型要求 channel_float = channel.astype(np.float32) # 创建ITK格式的输入图像 input_image = itk.image_from_array(channel_float) # 创建全1掩码(覆盖整个图像区域) mask_image = itk.image_from_array(np.ones_like(channel_float, dtype=np.uint8)) # 使用函数式接口执行N4偏置场校正 output_image = itk.n4_bias_field_correction(input_image, mask_image) # 将校正后的ITK图像转回NumPy数组 filtered.append(itk.array_from_image(output_image)) # 重新堆叠通道并替换原图像数据 image["image"] = np.stack(filtered) return image
额外检查
确认MONAI预处理管道中EnsureTyped输出的numpy数组类型是否为浮点型;若不是,可在N4转换前添加CastToTyped(keys=["image"], dtype=np.float32)步骤,避免类型不兼容问题。
内容的提问来源于stack exchange,提问作者Federico Digiacomo
相关产品推荐
相关产品推荐

