You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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数组),需要分两步执行:

  1. 将每个3D图像重采样/resize到目标形状(9,57,54)
  2. 把所有统一形状后的数组合并为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 23:50:26