如何将DICOM的pixel_array(np数组)正确写入CSV并还原原数组?
DICOM像素数组CSV存储与还原问题解决
一、关于现有CSV中数组的还原问题
首先得给你提个醒:你现在CSV里的像素数组字符串带...,这是因为写入时numpy自动截断了过长的数组显示,这部分被省略的数据已经丢失了,没办法完全还原成原始的完整数组。
如果是测试用的小型数组(没有省略号),可以用下面的方法把字符串转回numpy数组:
import numpy as np import pandas as pd import ast # 读取CSV文件 df = pd.read_csv('imgs_n_patied_train1.csv') # 定义字符串转数组的函数 def str_to_nparray(s): # 用ast解析字符串为列表,再转成numpy数组 return np.array(ast.literal_eval(s)) # 应用到pixel_array列 df['pixel_array'] = df['pixel_array'].apply(str_to_nparray)
但如果字符串里有...,这个方法会报错,而且丢失的中间数据也找不回来,所以更关键的是要解决如何正确写入CSV以保留完整数组的问题。
二、正确写入CSV保留完整像素数组的方法
直接把numpy数组写入CSV会触发它的默认字符串转换,长数组会被截断加省略号,所以我们需要换一种存储方式,下面给你两种实用方案:
方案1:展平数组为列表写入(推荐,高效)
把二维的像素数组展平成一维列表,写入CSV时就能保存所有数值,读取后再reshape回原始形状:
修改你的写入代码:
import numpy as np import csv import pydicom as dicom # 注意现在官方库名是pydicom,旧版dicom可能已弃用 def tryer(a, b): if b == 'pixel_array': # 展平数组并转为列表,确保所有数值都被写入 return a.pixel_array.flatten().tolist() else: try: return getattr(a, b) except AttributeError: return 'No' a_list = ['PatientID', 'pixel_array'] # 先获取样本图像的形状(假设所有DICOM图像尺寸一致) sample_img_path = r'pathto\stage_2_train_images\你的样本文件名.dcm' sample_img = dicom.read_file(sample_img_path, force=True) img_shape = sample_img.pixel_array.shape with open('imgs_n_patied_train1.csv', 'w', newline='') as f: thewriter = csv.writer(f) thewriter.writerow(['PatientID', 'pixel_array']) for i in imgs: img_path = fr'pathto\stage_2_train_images\{i}' a = dicom.read_file(img_path, force=True) app = [tryer(a, j) for j in a_list] thewriter.writerow(app)
读取时还原数组:
import pandas as pd import numpy as np df = pd.read_csv('imgs_n_patied_train1.csv') # 解析CSV中的列表字符串为一维数组,再reshape回原尺寸 def flat_list_to_array(s): num_list = list(map(int, s.strip('[]').split(','))) return np.array(num_list).reshape(img_shape) df['pixel_array'] = df['pixel_array'].apply(flat_list_to_array)
如果你的DICOM图像尺寸不一致,建议在CSV中多加一列image_shape,写入时保存a.pixel_array.shape,读取时用这个形状来reshape。
方案2:保存完整的数组字符串(适合小型数组)
用numpy.array2string生成不带省略号的完整数组字符串,写入CSV:
修改写入代码中的tryer函数:
def tryer(a, b): if b == 'pixel_array': # 生成完整的数组字符串,不截断,用逗号分隔 return np.array2string(a.pixel_array, separator=',', max_line_width=np.inf) else: try: return getattr(a, b) except AttributeError: return 'No'
读取时还原:
import pandas as pd import numpy as np import ast df = pd.read_csv('imgs_n_patied_train1.csv') df['pixel_array'] = df['pixel_array'].apply(lambda x: np.array(ast.literal_eval(x)))
额外建议
CSV其实并不适合存储大型像素数组,会导致文件体积超大、读写速度慢。如果可以的话,推荐使用HDF5或Parquet这类专为数值数据设计的格式,用pandas就能轻松实现:
# 保存为HDF5 df.to_hdf('dicom_data.h5', key='data', mode='w') # 读取 df = pd.read_hdf('dicom_data.h5', key='data')
内容的提问来源于stack exchange,提问作者Akshay Ram
相关产品推荐
相关产品推荐

