如何用NumPy拼接不同形状的3D数组得到指定4D数组?
解决NII图像数组合并为目标4D形状的问题
问题原因分析
你用np.append得到一维数组的核心原因是:np.append默认会将所有输入数组扁平化后再拼接,完全忽略原始数组的维度结构,最终得到的自然是一个一维长数组,不符合4D数组的需求。
另外,你的原始图像数组形状各不相同(比如第一个维度有9、8、6、4,后两个维度也存在差异),直接拼接本身就无法得到结构统一的4D数组,必须先将所有图像统一到目标形状(9,57,54),再进行合并。
解决方案:先统一图像形状,再合并
要得到(9,9,57,54)的4D数组(9个样本,每个样本为9×57×54的3D数组),需要分两步执行:
- 将每个3D图像重采样/resize到目标形状
(9,57,54) - 把所有统一形状后的数组合并为4D数组
方法一:用SimpleITK重采样(推荐用于医学图像)
医学图像的物理空间信息(间距、原点、方向)至关重要,用SimpleITK的重采样工具可以保留这些信息,避免空间错位:
import numpy as np import SimpleITK as sitk def resample_image(sitk_image, target_size): """将SimpleITK图像重采样到目标尺寸""" original_size = sitk_image.GetSize() original_spacing = sitk_image.GetSpacing() # 计算新的间距,保持物理空间范围一致 new_spacing = [ (original_size[i] * original_spacing[i]) / target_size[i] for i in range(3) ] resampler = sitk.ResampleImageFilter() resampler.SetSize(target_size) resampler.SetOutputSpacing(new_spacing) resampler.SetOutputDirection(sitk_image.GetDirection()) resampler.SetOutputOrigin(sitk_image.GetOrigin()) resampler.SetTransform(sitk.Transform()) resampler.SetDefaultPixelValue(sitk_image.GetPixelIDValue()) resampler.SetInterpolator(sitk.sitkLinear) # 线性插值适合医学图像 return resampler.Execute(sitk_image) # 定义目标参数:数组形状为(深度, 高度, 宽度),对应SimpleITK的尺寸顺序为(宽度, 高度, 深度) target_array_shape = (9, 57, 54) target_sitk_size = (target_array_shape[2], target_array_shape[1], target_array_shape[0]) processed_images = [] for item in images: img_org = nii_reader(item) # 重采样到目标尺寸 resampled_img = resample_image(img_org, target_sitk_size) # 转换为numpy数组 img_array = sitk.GetArrayFromImage(resampled_img) # 验证形状是否符合预期 assert img_array.shape == target_array_shape, f"重采样后形状不符:{img_array.shape} != {target_array_shape}" processed_images.append(img_array) # 合并为4D数组,形状为(样本数, 深度, 高度, 宽度) = (9,9,57,54) train = np.array(processed_images) print(train.shape)
方法二:直接resize数组(快速但不保留物理信息)
如果不需要考虑医学图像的物理空间属性,也可以用skimage直接对numpy数组进行resize:
import numpy as np import SimpleITK as sitk from skimage.transform import resize target_array_shape = (9, 57, 54) processed_images = [] for item in images: img_org = nii_reader(item) img_array = sitk.GetArrayFromImage(img_org) # resize到目标形状,preserve_range=True避免数值被归一化 resized_array = resize(img_array, target_array_shape, preserve_range=True) # 转换为原数组的数据类型,避免精度损失 resized_array = resized_array.astype(img_array.dtype) processed_images.append(resized_array) train = np.array(processed_images) print(train.shape)
关键说明
- 必须先统一所有图像的形状,否则无法合并为结构一致的4D数组
np.append不适合多维数组的批量合并,正确的做法是先将所有数组存入列表,再用np.array()或np.stack()合并,后者会自动创建新的维度作为样本轴。
内容的提问来源于stack exchange,提问作者Andi Muh. Syahrul Ulum
相关产品推荐
相关产品推荐

