使用pydicom合并大视频DICOM触发struct.error错误求助
问题描述
我用Python3的pydicom库合并多个含视频的DICOM文件,每个输入文件用pydicom.dcmread读取后,pixel_array是形状为(number_of_frames, rows, columns, 3)的NumPy数组,仅帧数不同。我把这些数组用numpy拼接成大数组,写入Dataset后调用save_as保存:
- 拼接后视频较小时,代码正常运行;
- 当视频尺寸达到
(6000,500,500,3)这类规模时,触发错误:
Traceback (most recent call last): File "...\Lib\site-packages\pydicom\tag.py", line 28, in tag_in_exception yield File "...\Lib\site-packages\pydicom\filewriter.py", line 662, in write_dataset write_data_element(fp, dataset.get_item(tag), dataset_encoding) File "...\Lib\site-packages\pydicom\filewriter.py", line 620, in write_data_element fp.write_UL(0xFFFFFFFF if is_undefined_length else value_length) File "...\Lib\site-packages\pydicom\filebase.py", line 119, in write_leUL self.write(pack(b"<L", val)) ^^^^^^^^^^^^^^^^ struct.error: argument out of range The above exception was the direct cause of the following exception: Traceback (most recent call last): File "...\dicom_concatenate.py", line 56, in work first_dicom.save_as(absolute_save_path) File "...\Lib\site-packages\pydicom\dataset.py", line 2061, in save_as pydicom.dcmwrite(filename, self, write_like_original) File "...\Lib\site-packages\pydicom\filewriter.py", line 1153, in dcmwrite _write_dataset(fp, dataset, write_like_original) File "...\Lib\site-packages\pydicom\filewriter.py", line 889, in _write_dataset write_dataset(fp, get_item(dataset, slice(0x00010000, None))) File "...\Lib\site-packages\pydicom\filewriter.py", line 661, in write_dataset with tag_in_exception(tag): File "...\contextlib.py", line 155, in __exit__ self.gen.throw(typ, value, traceback) File "...\Lib\site-packages\pydicom\tag.py", line 32, in tag_in_exception raise type(exc)(msg) from exc struct.error: With tag (7fe0, 0010) got exception: argument out of range Traceback (most recent call last): File "...\Lib\site-packages\pydicom\tag.py", line 28, in tag_in_exception yield File "...\Lib\site-packages\pydicom\filewriter.py", line 662, in write_dataset write_data_element(fp, dataset.get_item(tag), dataset_encoding) File "...\Lib\site-packages\pydicom\filewriter.py", line 620, in write_data_element fp.write_UL(0xFFFFFFFF if is_undefined_length else value_length) File "...\Lib\site-packages\pydicom\filebase.py", line 119, in write_leUL self.write(pack(b"<L", val)) ^^^^^^^^^^^^^^^^ struct.error: argument out of range
错误原因
这个错误的核心是DICOM的像素数据长度超出了无符号长整型(UL)的最大值:
- 标签
(7fe0, 0010)是DICOM中的像素数据(Pixel Data)字段; - 无符号长整型(UL)的最大值是
0xFFFFFFFF(即4294967295字节,约4GB); - 拼接后的像素数据总大小为
6000*500*500*3 = 4500000000字节,已经超过4GB上限,导致pydicom在尝试用struct.pack写入UL类型的长度值时,因数值超出范围触发struct.error。
解决方法
方法1:使用未定义长度存储像素数据
pydicom支持对大尺寸数据使用未定义长度,写入时会自动分片段存储,避开UL的长度限制。修改保存逻辑:
# 直接使用dcmwrite并指定参数 pydicom.dcmwrite(absolute_save_path, first_dicom, write_like_original=False, transfer_syntax=pydicom.uid.ImplicitVRLittleEndian)
或手动设置未定义长度:
# 写入拼接后的像素数据 first_dicom.PixelData = concatenated_array.tobytes() # 标记像素数据使用未定义长度 first_dicom.is_undefined_length('PixelData') = True # 保存时禁用原格式写入 first_dicom.save_as(absolute_save_path, write_like_original=False)
方法2:拆分DICOM文件
如果必须使用固定长度存储,可将大视频拆分为多个符合4GB限制的DICOM文件,比如按每4000帧拆分(4000500500*3=3000000000字节,约2.79GB,小于4GB)。
方法3:使用压缩传输语法
若原始DICOM为未压缩格式,换成压缩传输语法(如JPEG 2000无损压缩)可大幅减小像素数据体积,从而避免超出长度限制:
from pydicom.uid import JPEG2000Lossless # 保存时指定压缩传输语法 pydicom.dcmwrite(absolute_save_path, first_dicom, write_like_original=False, transfer_syntax=JPEG2000Lossless)
注意:使用压缩语法需确保pydicom的依赖库(如pylibjpeg及对应编解码器)已安装。
内容的提问来源于stack exchange,提问作者温泽海
相关产品推荐
相关产品推荐

