用MATLAB改写DICOM文件中的图像数据

本文分享了如何通过MATLAB将二维图像数据转换为DICOM格式的过程,包括获取DICOM文件头部信息、定位图像数据存储位置及实际写入操作。讨论了利用MATLAB直接写入DICOM文件的方法,并对比了使用dicomwrite函数的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


        前段时间由于一项TASK的需求,要根据原有的一组DICOM文件的信息将一组另外生成的二维图像数据重新写成DICOM文件格式以作后续使用,我采取了通过MATLAB写文件的方式把这个二维图像数据写到原DICOM文件中存储图像数据的部分。这里主要想跟大家分享一下我尝试这个操作的方法和流程。

       为了实现这个操作,第一步就是要去获取DICOM的二进制文件中图像数据存储的起始位置,那么如何去获取,这就需要对DICOM文件格式的结构有比较清晰的把握。通过查阅相关资料(这里非常感谢zssure提供的DICOM3.0标准的详细说明),可以了解到DICOM文件主要分为文件头和数据集两部分,那么在这里根据相关资料中的内容我们可以对DICOM文件格式的这样两部分作一个简要的介绍。

1、文件头,它主要包括两个部分,第一部分是导言(Preamble),一般是由128个字节的00h所填充,紧接着第二部分是文件前缀,内容是“44 49 43 4D”这样四个字节代表ASCII码对应的大写字母字符串“DICM”;

2、数据集,它是由数据元素按照数据标签(Tag)的升序排列而成,主要用来存储具体信息 ,包括传输语法,病人姓名,文件元信息版本,媒体存储SOP类UID,传输句法UID,以及图像的属性和数据内容方面的信息等等。而数据元素主要是由四个成分组成:标签(Tag),值表示类型(VR Value Representation),值长度(Value Length),值域(Value Field)。

下面我们给出一个例子,如下表所示。



这里我同时截取了用UltraEdit打开DICOM文件时看到的十六进制数排列图

通过上表与上图的对照,我们可以清楚地看到DICOM文件头部分数据的排列,而接着从“02 00 00 00”对应的数据标签(0002 0000)开始以数据元素为单位进行各类信息的顺序存储。那么文件整体结构即可用paper里的图表示,见下图:



        据此,可初步估计我所需要知道的图像数据应当存储于某一个数据元素单元的数据值中。然后,通过继续查阅资料,搜索到了标签为(7FE0 0010)的数据元素单元正是包含了DICOM图像显示所需要的数据。这里我给出了这个数据元素的一个实例,如下图所示。


对于该数据元素,我们将它对应到之前所述的四个组成成分[Tag VR VL VF],可以得出(7FE0,0010)的四个字节对应Tag,(4F 57 00 00)的四个字节对应VR为OW类型,数据长度VL为(0001 2000)=73728个字节(PS:这里注意数据的存放方式是Little-Endian,即小端模式),作为验证,你可以check一下这个字节数应当等于图像行数×图像列数×2(PS:其中,标签(0028,0010)对应的是图像行数,(0028,011)对应的是图像列数,(0028,0100)对应的是分配位数,这个位数通常为16bits,即用2个字节存储一个像素的数据),另一方面你也可以check一下这个字节数同时也应当等于从该单元内数据值开始的地址(如这里从地址2140h开始)到文件末尾地址所存储的字节数。

        OK,在找到图像数据元素的存储位置之后,剩下的就是写数据的工作了。起初可能由于解读DICOM文件格式的惯性思维,还想用存有图像数据的mat文件直接写入DICOM文件,但是发现mat文件的格式不是那么容易找到相关资料解析的,于是还是采用matlab中的文件写函数将数据直接写入到DICOM文件中的图像数据存储位置进行替换。

       总体来说呢,在matlab中实现这部分操作还是蛮简单的,只需要几行code就可以实现,这里我把关键的一部分列在这里供大家参考。


       其中,idx即是找到图像数据元素单元对应标签7FE0,0010)的位置,然后从‘E0’开始之后的第12个字节处即为图像数据存储的首地址,亦即图像数据在这个DICOM二进制文件中的offset,从此处将已经生成的图像数据写入到原DICOM文件的相应部分即可。

       这里能够很快完成这部分尝试性的操作还要非常感谢zssure同志的建议和鼓励,在此写下自己在这个过程中所了解到的一些知识以及解决问题过程中的一些经验来与大家分享,希望可以帮助到有可能会有类似操作需求的人们,可能算是小众群体吧,嘿嘿~

       另外呢,将自己生成的图像数据重新写成DICOM文件还有另一种方法就是直接利用matlab中的dicomwrite函数,但很多时候利用这个函数将已有的dicominfo写入到新的dicom文件中时会丢失或者改写一些信息,尤其是private parameter的部分,我曾经通过改写matlab的内部函数解决过其中的一些参数写入不全的问题,如果有对此操作感兴趣的同志也可以给我留言啦。

       

MATLAB代码转换成Python文件的过程可以分为几个步骤: 1. **理解代码结构**:首先,你需要熟悉MATLAB代码的功能,了解它做了哪些操作,比如文件读取、数据分析、图像处理等。 2. **导入必要的库**:在Python中,可能需要像`matplotlib``pydicom`这样的库来代替MATLAB中的`figure``dicomreadVolume`函数。 3. **语法转换**: - 将MATLAB变量名函数名改写为Python语法(如变量名首字母小写,函数名全部小写且无下划线分隔) - 把MATLAB的指令(如`for`循环、条件判断等)转换成Python的相应语法 4. **替换函数**: - 将MATLAB的内置函数如`dir`换成Python的类似功能,例如`os.listdir`来列出文件夹内容 - 对于图像处理相关的函数,可以使用`PIL`(Python Imaging Library)或`scikit-image`库 5. **保存文件**:创建一个新的`.py`文件,逐行复制并修改MATLAB代码,最后保存文件。 示例代码转换: ```python import os from pydicom import dcmread import matplotlib.pyplot as plt # 添加路径至sys.path # (这在Python中不需要,但在MATLAB中类似) # addpath(genpath('C:\\Users\\ASUS\\Desktop\\医学影像\\LIDC-IDRI-0001')) subfile = 'C:\\Users\\ASUS\\Desktop\\医学影像\\LIDC-IDRI-0001' images_path = os.listdir(subfile) for i, img_folder in enumerate(images_path): subfolder_path = os.path.join(subfile, img_folder) if not os.path.isdir(subfolder_path): continue for img_file in os.listdir(subfolder_path): img_path = os.path.join(subfolder_path, img_file) # 在Python中读取DICOM文件 with dcmread(img_path) as img_data: img = img_data.pixel_array img = img.squeeze() plt.figure(figsize=(8, 8)) plt.imshow(img, cmap='gray') plt.show() # ...其他部分的代码转换类似 ```
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值