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

如何读取多帧DICOM文件并在UI中直接显示为视频

直接在Tkinter中显示多帧DICOM(无需保存为GIF)

核心思路

  • 用pydicom读取多帧DICOM的原始像素数据
  • 借助PIL将DICOM像素数据转换为Tkinter支持的PhotoImage格式
  • 利用Tkinter的after()方法循环更新Label的图像,实现类视频的播放效果

完整代码示例

import tkinter as tk
from pydicom import dcmread
from pydicom.pixel_data_handlers.util import apply_voi_lut
from PIL import Image, ImageTk
import numpy as np

def load_dicom_frames(dicom_path):
    """加载多帧DICOM并返回处理后的Tkinter图像列表"""
    ds = dcmread(dicom_path)
    # 获取多帧像素数据,shape为(帧数, 图像高度, 图像宽度)
    pixel_data = ds.pixel_array
    
    frames = []
    for frame in pixel_data:
        # 应用窗宽窗位调整,还原医学影像的标准显示效果
        img = apply_voi_lut(frame, ds)
        
        # 将非8位深度的像素数据归一化到0-255范围
        if img.dtype != np.uint8:
            img = (img - img.min()) / (img.max() - img.min()) * 255
            img = img.astype(np.uint8)
        
        # 转换为Tkinter可识别的图像格式
        pil_img = Image.fromarray(img)
        tk_img = ImageTk.PhotoImage(pil_img)
        frames.append(tk_img)
    
    return frames

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="直接在Tkinter中播放多帧DICOM")
    parser.add_argument("dicom_image", help="目标DICOM文件的路径")
    args = parser.parse_args()
    
    root = tk.Tk()
    root.title("多帧DICOM播放器")
    
    # 加载并处理所有DICOM帧
    dicom_frames = load_dicom_frames(args.dicom_image)
    frame_count = len(dicom_frames)
    
    # 创建用于显示图像的Label组件
    label = tk.Label(root)
    label.pack()
    
    def update_frame(index):
        """循环更新显示的帧,实现播放效果"""
        current_frame = dicom_frames[index]
        label.config(image=current_frame)
        # 计算下一帧索引,实现循环播放
        next_index = (index + 1) % frame_count
        # 每隔100ms更新一次,可根据需求调整播放速度
        root.after(100, update_frame, next_index)
    
    # 启动播放
    update_frame(0)
    
    root.mainloop()

关键细节说明

  • 像素数据处理:DICOM像素常为16位深度,需归一化转8位,同时应用VOI LUT(窗宽窗位)保证医学影像的正确视觉呈现。
  • 内存管理:必须用列表持有所有PhotoImage对象,避免被Python垃圾回收机制清理,导致图像无法显示。
  • 播放速度:调整root.after()的时间参数(单位:毫秒)即可控制帧率,比如100ms对应10帧/秒。

内容的提问来源于stack exchange,提问作者Ron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:45:57