如何使用pydicom正确替换DICOM图像中的像素数据?
问题1:属性赋值报错原因
AttributeError: can't set attribute 报错的核心原因是 pixel_array 是pydicom数据集对象的只读派生属性,它是从底层二进制字段 PixelData 动态解析生成的numpy数组,本身不支持直接赋值。你后续改为直接给PixelData字段写入二进制字节流的操作是正确的,解决了该报错。
问题2:替换后图像不匹配的原因及修复方案
仅修改Rows、Columns、PixelData三个字段不足以让DICOM正确解析像素值,还需要同步修改所有和像素编码、解析规则相关的元数据字段,遗漏的配置项如下:
- 位深配置:需要和你的
data[layer]数组的dtype完全匹配BitsAllocated:每个像素分配的存储比特位,比如数组为int16/uint16类型时该值设为16BitsStored:像素实际有效数据的比特位,比如12位CT数据就设为12,一般不超过BitsAllocatedHighBit:像素有效数据的最高位下标,通常等于BitsStored - 1PixelRepresentation:像素值的符号标识,0为无符号整数,1为有符号整数,要和数组dtype对应(uint类选0,int类选1)
- 光度解释配置:
PhotometricInterpretation,标识灰度/彩色的解析规则,CT类灰度图一般为MONOCHROME2(数值越高越亮),如果配置为MONOCHROME1会出现明暗反转的问题 - 灰度映射配置:
RescaleSlope和RescaleIntercept,DICOM显示时会用公式实际显示值 = 原始像素值 * RescaleSlope + RescaleIntercept做转换,如果你写入PixelData的就是需要直接显示的灰度值,将RescaleSlope设为1、RescaleIntercept设为0即可 - 字节序匹配:如果替换后图像出现乱码噪点,可检查
data[layer]的字节序和DICOM默认字节序是否一致,不一致的话使用data[layer].byteswap().tobytes()写入即可
修正后的参考代码
import matplotlib.pyplot as plt from pydicom import dcmread from pydicom.data import get_testdata_file import numpy as np # 此处为示例构造的测试数组,替换为你自己的data[layer]即可 data = np.random.randint(low=-1000, high=2000, size=(1, 200, 200), dtype=np.int16) layer = 0 fpath = get_testdata_file('CT_small.dcm') ds = dcmread(fpath) # 修改行列分辨率 ds.Rows = 200 ds.Columns = 200 # 同步更新像素元数据,匹配你的数组属性 ds.BitsAllocated = 16 ds.BitsStored = 12 ds.HighBit = 11 ds.PixelRepresentation = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.RescaleSlope = 1 ds.RescaleIntercept = 0 # 写入像素二进制数据 ds.PixelData = data[layer].tobytes() # 验证输出 plt.imshow(ds.pixel_array, cmap='gray') plt.show()
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

