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

使用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,提问作者温泽海

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 08:37:06