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

使用np.load加载DICOM图像失败及维度异常问题求助

图像处理DICOM数据加载问题排查

问题1:IMAGE_SPATIAL_DIMS输出为3而非预期三维形状

运行以下代码时:

import numpy as np
...
file_name = "/content/drive/MyDrive/.../1-01.dcm"
IMAGE_SPATIAL_DIMS = np.load(file_name)[...,0].shape

预期得到类似(128, 128, 16)的三维形状,实际输出结果为3。

问题2:加载预处理图像时的Pickle错误

  • 初始报错:ValueError: Cannot load file containing pickled data when allow_pickle=False
  • 设置allow_pickle=True后仍报错:UnpicklingError: Failed to interpret file '1-01.dcm' as a pickle

预处理代码

import os
import sys
import shutil
import numpy as np
import pandas as pd
import pydicom as dicom
from os.path import join
import SimpleITK as sitk
from spire.xls import *
from spire.xls.common import *
import openpyxl as op
import time

### Read TrainFold0 Excel Sheet
CODE_BASE = os.path.abspath('/content/drive/MyDrive/MasterThesis')
TRAIN_XLSX = '/content/drive/MyDrive/MasterThesis/.../Datasets/TrainFold0.xlsx'

### Make DataFrame of 3D Data
dataFrame = pd.read_excel(TRAIN_XLSX)

### Create First Row of DataFrame3D
dataFrame3D = pd.DataFrame()

### Make 3D Train Data Directory
Data3D_path = '/content/drive/MyDrive/MasterThesis/.../Datasets/3DPROSTATEx'
if not(os.path.exists(Data3D_path)):
  os.mkdir(Data3D_path)
### Load an TrainFold Excel File
wb = op.load_workbook(filename=TRAIN_XLSX)
ws = wb.active

### Read DataFrame of TrainFold Excel File
dataFrame = pd.read_excel(TRAIN_XLSX)
col_imagePath = dataFrame['image_path']

### Get the Number of Rows
row_num = len(col_imagePath)

### Read the image_path of Every Row
last_indx = 0
for row_count in range(row_num):
  print('row_count: '+str(row_count))
  path = col_imagePath[row_count]
  path_3D =  "/".join(path.split('/')[2:-1])
  #print(path)
  #print(path_3D)
  ### Make Directory for Image3D
  for i in range(1, len(path_3D.split('/'))+1):
    if not(os.path.exists(Data3D_path + '/' + "/".join(path_3D.split('/')[:i]))):
      os.mkdir(Data3D_path + '/' + "/".join(path_3D.split('/')[:i]))

  ### Make a New Name for 3D Image
  #e.g : path_3D = 'ProstateX-0030/10-30-2011-NA-MC prostaat kliniek detectie-mc MCPROSKL30-54485/3.000000-t2tsesag-6352'
  part1  = path_3D.split('/')[0]                                 #e.g: ProstateX-0030
  part11 = part1.split('-')[1]                                   #e.g: 0030

  part2  = path.split('/')[-1]                                   #e.g: 3.000000-t2tsesag-6352
  part21 = part2.split('-')[0]                                   #e.g: 3.000000
  part22 = part21.split('.')[0]                                  #e.g: 3

  image3D_Name = part11+ '-' + str(part22).rjust(2, '0')+'.dcm'  #e.g: 0030-03.dcm
  #time.sleep(5)
  ### If Related 3D Image Doesn't Exist Create it
  if (os.path.exists(Data3D_path +'/'+ path_3D+'/'+image3D_Name)):
    print(str(image3D_Name)+'Image Does not Exist')
    ### Get Images in Directory
    os.chdir('/content/drive/MyDrive/MasterThesis/.../Datasets'+path)
    entries = os.listdir('/content/drive/MyDrive/MasterThesis/.../Datasets'+path)

    image3D = []
    for entry in entries:
      ### Check if Entry doesn't Image ,pass away this loop and go to the next entry
      if not(os.path.isfile(entry)):
        continue

      ### Read DICOM Image as a Slice
      #new_slice = dicom.dcmread(entry).pixel_array

      ### Read DICOM Image with numpy.load
      new_slice = np.load(entry)
      ### Expand Dimension of Slice Image from [Height, Width] to [Height, Width, 1]
      new_slice3D = np.expand_dims(new_slice, axis=2)
      if len(image3D)!=0 :
        ### Append New Slice to 3D Image
        image3D = np.append(image3D, new_slice3D, axis=2)
      else:
        ### Create Frist Slice
        image3D = new_slice3D

    ### Save Image3D in Related Directory
    os.chdir(Data3D_path +'/'+ path_3D)
    iMAGE_TRAIN_3D = sitk.GetImageFromArray(image3D)
    sitk.WriteImage(iMAGE_TRAIN_3D, Data3D_path +'/'+ path_3D +'/'+ image3D_Name)

  ### Export Path of Image3D in DataFrame3D
  new_row = dataFrame.iloc[[row_count]].copy()

  ### Concatenate New Row to dataFrame3D
  dataFrame3D = pd.concat([dataFrame3D, dataFrame.iloc[[row_count]].copy()] , axis=0, ignore_index=True)

  ### Change Old Path to New Path
  dataFrame3D.loc[dataFrame3D.index[-1],'image_path'] = Data3D_path+'/'+ path_3D+'/'+ image3D_Name

  ### Convert DataFrame3D to TrainFold3D Excel File
  dataFrame3D.to_csv(join(TRAIN_XLSX_PREFIX+'3D.csv'))

问题分析与解决

核心错误根源

你全程误用了np.load()读取DICOM文件:np.load()仅支持读取numpy专属的.npy/.npz格式文件,而DICOM是医学影像专用格式,两者完全不兼容,这是所有问题的起点。

1. 解决shape输出为3的问题

改用DICOM专用库读取文件,再转换为numpy数组获取形状:

方法1:用SimpleITK读取(匹配你预处理时的保存方式)

import SimpleITK as sitk
file_name = "/content/drive/MyDrive/.../1-01.dcm"
# 读取DICOM文件
sitk_image = sitk.ReadImage(file_name)
# 转换为numpy数组(注意顺序为(z, y, x))
image_array = sitk.GetArrayFromImage(sitk_image)
# 若需要(y, x, z)的顺序,可转置
IMAGE_SPATIAL_DIMS = image_array.transpose(1, 2, 0).shape

方法2:用pydicom读取

import pydicom
file_name = "/content/drive/MyDrive/.../1-01.dcm"
ds = pydicom.dcmread(file_name)
# 多帧DICOM的pixel_array为(z, y, x)形状
IMAGE_SPATIAL_DIMS = ds.pixel_array.shape

2. 解决Pickle错误问题

直接弃用np.load()读取DICOM文件,改用上述两种DICOM专用读取方式即可,无需调整allow_pickle参数。

预处理代码的关键修正

  1. 修正切片读取逻辑:把错误的new_slice = np.load(entry)替换为正确的DICOM读取代码:
    # 替换原错误代码
    ds = dicom.dcmread(entry)
    new_slice = ds.pixel_array
    
  2. 修正文件存在判断逻辑:原代码中if (os.path.exists(...)):逻辑颠倒,应改为:
    if not os.path.exists(Data3D_path +'/'+ path_3D+'/'+image3D_Name):
    
  3. 避免工作目录切换:用绝对路径拼接代替os.chdir,防止路径混乱:
    slice_dir = '/content/drive/MyDrive/MasterThesis/.../Datasets'+path
    entries = os.listdir(slice_dir)
    for entry in entries:
        entry_path = os.path.join(slice_dir, entry)
        if not os.path.isfile(entry_path):
            continue
        # 后续读取操作使用entry_path
    
  4. 优化DataFrame保存:把dataFrame3D.to_csv()移到循环结束后,避免重复写入浪费资源。

内容的提问来源于stack exchange,提问作者zahra mrtz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:59:57