如何正确合成多帧DICOM?PNG转DICOM帧显示异常问题排查
多帧OCT图像转DICOM时帧重叠/裁剪问题解决
问题描述
将300余张连续PNG格式光学相干断层扫描(OCT)图像合成为多帧DICOM文件,已生成含375帧的文件,但帧图像出现重叠、裁剪,与原单帧PNG图像显示效果不符。
原代码
import os import datetime import numpy as np import pydicom.encaps from PIL import Image from pydicom.dataset import FileMetaDataset, Dataset from pydicom.uid import ExplicitVRLittleEndian dt = datetime.datetime.now() # Image folder and its contents image_folder = r"E:\OCT\series_00\US000000" image_files = [f for f in os.listdir(image_folder) if f.endswith('.png')] image_files.sort() # DICOM file metadata file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.14.1' file_meta.ImplementationClassUID = '1.2.3.4' # Create a new multi-frame DICOM dataset multi_frame_dataset = Dataset() multi_frame_dataset.SOPClassUID = '1.2.840.10008.5.1.4.1.1.14.1' multi_frame_dataset.PatientName = "Test^Name" multi_frame_dataset.PatientID = "00-000-000" multi_frame_dataset.ContentDate = dt.strftime('%Y%m%d') multi_frame_dataset.ContentTime = dt.strftime('%H%M%S.%f') multi_frame_dataset.is_little_endian = True multi_frame_dataset.is_implicit_VR = False multi_frame_dataset.SpecificCharacterSet = 'ISO_IR 100' # List with 'pixel arrays' of all images (frames) pixel_data = [] # Load and append each image to the pixel data list: for image_file in image_files: image_path = os.path.join(image_folder, image_file) image = Image.open(image_path) pixel_array = np.array(image) pixel_data.append(pixel_array) multi_frame_pixel_data = pydicom.encaps.encapsulate([frame.tobytes() for frame in pixel_data]) # Combine pixel data from all frames into the multi-frame DICOM multi_frame_dataset.PixelData = multi_frame_pixel_data multi_frame_dataset.Rows = pixel_data[0].shape[0] multi_frame_dataset.Columns = pixel_data[0].shape[1] multi_frame_dataset.NumberOfFrames = len(pixel_data) # Set attributes for the multi-frame DICOM multi_frame_dataset.SamplesPerPixel = 3 multi_frame_dataset.BitsAllocated = 8 multi_frame_dataset.BitsStored = 8 multi_frame_dataset.HighBit = 7 multi_frame_dataset.PixelRepresentation = 0 # Save the multi-frame DICOM file save_path = r'C:\Desktop\New Folder\multi_frame.dcm' multi_frame_dataset.save_as(save_path)
输出对比
- 实际输出(帧重叠裁剪):

- 预期输出(单帧原图像):

问题根源与修正方案
1. 通道格式不匹配
PNG图像默认可能为RGBA(4通道),但代码强制设置SamplesPerPixel = 3,导致像素数据长度不匹配,触发阅读器解析错误,需统一转换为RGB格式。
2. 缺少颜色空间定义
未设置PhotometricInterpretation属性,DICOM阅读器无法正确识别颜色空间,导致渲染异常,RGB图像需明确设置该属性为RGB。
3. 元数据不完整
未关联合法的SOP实例UID,且部分文件元数据未正确绑定到数据集,影响DICOM文件的合规性。
修正后的代码
import os import datetime import numpy as np import pydicom.encaps from PIL import Image from pydicom.dataset import FileMetaDataset, Dataset from pydicom.uid import ExplicitVRLittleEndian, generate_uid dt = datetime.datetime.now() # 图像文件夹路径 image_folder = r"E:\OCT\series_00\US000000" image_files = [f for f in os.listdir(image_folder) if f.endswith('.png')] image_files.sort() # 文件元数据(必须正确关联到数据集) file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.14.1' # OCT多帧SOP类 file_meta.MediaStorageSOPInstanceUID = generate_uid() file_meta.ImplementationClassUID = '1.2.3.4' file_meta.TransferSyntaxUID = ExplicitVRLittleEndian # 创建多帧DICOM数据集 multi_frame_dataset = Dataset() multi_frame_dataset.file_meta = file_meta multi_frame_dataset.is_little_endian = True multi_frame_dataset.is_implicit_VR = False multi_frame_dataset.SOPClassUID = '1.2.840.10008.5.1.4.1.1.14.1' multi_frame_dataset.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID multi_frame_dataset.PatientName = "Test^Name" multi_frame_dataset.PatientID = "00-000-000" multi_frame_dataset.ContentDate = dt.strftime('%Y%m%d') multi_frame_dataset.ContentTime = dt.strftime('%H%M%S.%f') multi_frame_dataset.SpecificCharacterSet = 'ISO_IR 100' # 处理每帧图像,统一转换为RGB格式 pixel_data = [] for image_file in image_files: image_path = os.path.join(image_folder, image_file) with Image.open(image_path) as img: # 转换为RGB,丢弃Alpha通道 rgb_img = img.convert("RGB") pixel_array = np.array(rgb_img) # 确保像素数据内存布局符合DICOM要求 pixel_array = np.ascontiguousarray(pixel_array) pixel_data.append(pixel_array) # 封装多帧像素数据 multi_frame_pixel_data = pydicom.encaps.encapsulate([frame.tobytes() for frame in pixel_data]) # 设置像素相关属性 multi_frame_dataset.PixelData = multi_frame_pixel_data multi_frame_dataset.Rows = pixel_data[0].shape[0] multi_frame_dataset.Columns = pixel_data[0].shape[1] multi_frame_dataset.NumberOfFrames = len(pixel_data) multi_frame_dataset.SamplesPerPixel = 3 multi_frame_dataset.BitsAllocated = 8 multi_frame_dataset.BitsStored = 8 multi_frame_dataset.HighBit = 7 multi_frame_dataset.PixelRepresentation = 0 # 关键:添加颜色空间定义 multi_frame_dataset.PhotometricInterpretation = "RGB" # 保存文件 save_path = r'C:\Desktop\New Folder\multi_frame.dcm' multi_frame_dataset.save_as(save_path, write_like_original=False)
关键修改点说明
- 强制将PNG图像转换为RGB格式,避免Alpha通道干扰
- 添加
PhotometricInterpretation = "RGB",明确颜色空间 - 生成并关联合法的
SOPInstanceUID,完善文件元数据 - 使用
np.ascontiguousarray确保像素数据内存布局符合DICOM要求 - 保存时指定
write_like_original=False,确保元数据正确写入
内容的提问来源于stack exchange,提问作者Daniel Gustavo
相关产品推荐
相关产品推荐

