【代码 | 格式转换】Dicom转png

时间:2022-11-06 01:12:41

 【相关链接】

How To Convert a DICOM Image Into JPG or PNG - PYCAD中文

【相关知识】

1、PNG和JPEG(JPG)格式各有优缺点,根据不同的应用场景可以选择不同的格式。

从保留图片信息的完整性和减少信息丢失的角度来看,PNG格式比JPEG格式更好。PNG是一种无损压缩格式,可以保留图像的每个像素的完整信息,并且不会引起压缩失真。因此,当需要在图像处理中保留最高质量的图像信息时,通常选择PNG格式。

相比之下,JPEG格式是一种有损压缩格式,压缩时会丢失图像的一些信息,导致图像质量下降。虽然JPEG格式的压缩比较高,文件大小比PNG格式小,但JPEG格式在图像处理中可能会导致信息丢失和质量下降。

总的来说,如果您需要在图像处理中保留最高质量的图像信息,则应选择PNG格式。如果文件大小比较重要,而图像质量不是最高优先级,则可以选择JPEG格式。

2、DICOM(Digital Imaging and Communications in Medicine)是医学图像和相关信息的标准格式。要读取DICOM文件,可以使用DICOM库,例如pydicom

虽然DICOM最初是为CT(计算机断层扫描)图像设计的,但它现在也广泛用于其他医学成像设备产生的图像,包括X射线片,核磁共振(MRI),超声波,PET等。

因此,DICOM格式的文件不一定是CT,也可以是X光片或其他医学成像设备的图像。DICOM格式为各种医学图像提供了一种标准的方式,使它们可以在不同的医学成像设备和软件之间交换和共享。

由.DCM转成.PNG时:DICOM格式的医学影像数据存储了大量的元数据和像素数据,而PNG格式的图像数据只包含像素数据。在转换过程中,需要注意DICOM数据可能包含了压缩编码,需要使用pydicom库进行解码。同时,由于DICOM文件中的像素值可能不是标准的8位灰度值,需要进行归一化处理,确保像素值的范围在0到255之间。

【代码记录】

1、使用pydicom读取DICOM文件信息

中间出现报错:UnicodeEncodeError: 'gbk' codec can't encode character '\xcd' in position 3694: illegal multibyte sequence因为有些Unicode字符无法编码

# -*- coding: utf-8 -*-
import pydicom
import sys

# 将输出编码格式设置为utf-8
sys.stdout.reconfigure(encoding='utf-8')

# 读取DICOM文件
ds = pydicom.dcmread('-0001-0001-0001-W4095L2047.DCM')  # .dcm

# 打印DICOM数据集信息
print(ds.__repr__().encode('utf-8').decode('unicode_escape'))

(0018, 1050) Spatial Resolution DS: '0.143' 表示图像的空间分辨率为 0.143mm,空间分辨率是指在图像上相邻两个像素之间的物理距离。
(0028, 0030) Pixel Spacing DS: [0.1408399617591, 0.1408399617591]

Pixel SpacingImager Pixel Spacing都是描述像素之间间距的DICOM属性,但是它们描述的是不同的像素间距。

Imager Pixel Spacing描述的是数字图像显示设备(imager)中的像素间距,它是一个由两个数字组成的列表,第一个数字表示行间距,第二个数字表示列间距,单位是mm。

Pixel Spacing描述的是图像平面(pixel array)中的像素间距,它是一个由两个数字组成的列表,第一个数字表示行间距,第二个数字表示列间距,单位也是mm。

在本例中,Imager Pixel Spacing的值是[0.143, 0.143],表示数字图像显示设备中相邻像素的行间距和列间距都是0.143mm。而Pixel Spacing的值是[0.1408399617591, 0.1408399617591],表示图像平面中相邻像素的行间距和列间距都是0.1408399617591mm。可以看出,两者的值略有不同,可能是由于数字图像显示设备的插值等因素导致的差异。

2、提取多文件夹下.DCM文件到指定统一目录下

一共有80个,但是总是只能提取出22个,Debug之后发现是不同子目录下的最后.DICOM文件名称相同,导致少提取了很多,让医生重新导出要占用就诊时间,那就加一个文件名判断。

(1)只顾提取(.DCM不重名)

# -*- coding: utf-8 -*-
import os
import shutil

# 设置根目录
root_dir = 'F:/0-MINE-coding/0DataProcess/dicom2png/4'

# 设置目标文件夹
target_dir = 'F:/0-MINE-coding/0DataProcess/dicom2png/20230330'

# 遍历目录树
for dirpath, dirnames, filenames in os.walk(root_dir):
    for filename in filenames:
        # 如果是.DCM文件
        if filename.endswith('.DCM'):
            # 拼接完整路径
            filepath = os.path.join(dirpath, filename)
            # 复制到目标文件夹
            shutil.copy2(filepath, target_dir)

(2)如有同名,加个序号(i)        os.path.exists()来判断目标文件夹中是否存在同名文件

import os
import shutil

# 设置根目录
root_dir = 'F:/0-MINE-coding/0DataProcess/dicom2png/4'

# 设置目标文件夹
target_dir = 'F:/0-MINE-coding/0DataProcess/dicom2png/20230330_1'

# 遍历目录树
for dirpath, dirnames, filenames in os.walk(root_dir):
    for filename in filenames:
        # 如果是.DCM文件
        if filename.endswith('.DCM'):
            # 拼接完整路径
            filepath = os.path.join(dirpath, filename)

            # 如果目标文件夹中已存在同名文件,则在文件名中加入序号
            if os.path.exists(os.path.join(target_dir, filename)):
                i = 1
                while True:
                    new_filename = filename.split('.DCM')[0] + f' ({i}).DCM'
                    if not os.path.exists(os.path.join(target_dir, new_filename)):
                        break
                    i += 1
                shutil.copy2(filepath, os.path.join(target_dir, new_filename))
            else:
                shutil.copy2(filepath, target_dir)

 3、一张.DCM转成.png

先是得到一片漆黑的图片,然后得到一张全白的图片(只有天赋异禀的人才能看得到( •̀ ω •́ )V

可能是像素值的范围设置不正确导致的,将像素值的范围调整到 [0, 255],然后再保存为 PNG 文件。

# -*- coding: utf-8 -*-
import numpy as np
import pydicom
from PIL import Image

# 读取 DICOM 文件
ds = pydicom.dcmread("-0001-0001-0001-W4095L2047.DCM")

# 将像素值的范围调整到 [0, 255]
pixel_array = ds.pixel_array
min_value = np.min(pixel_array)
max_value = np.max(pixel_array)
pixel_array = (pixel_array - min_value) / (max_value - min_value) * 255
pixel_array = pixel_array.astype(np.uint8)

# 创建 PIL Image 对象
image = Image.fromarray(pixel_array)

# 保存为 PNG 文件
image.save("-0001-0001-0001-W4095L2047.png")

4、dicom2png批处理

# -*- coding: utf-8 -*-
import os
import numpy as np
import pydicom
from PIL import Image

# 设置根目录
root_dir = './20230330'

# 设置目标文件夹
target_dir = './20230330_png'

# 遍历目录树
for dirpath, dirnames, filenames in os.walk(root_dir):
    for filename in filenames:
        # 如果是.DICOM文件
        if filename.endswith('.DCM'):
            # 拼接完整路径
            filepath = os.path.join(dirpath, filename)

            # 读取 DICOM 文件
            ds = pydicom.dcmread(filepath)

            # 将像素值的范围调整到 [0, 255]
            pixel_array = ds.pixel_array
            min_value = np.min(pixel_array)
            max_value = np.max(pixel_array)
            pixel_array = (pixel_array - min_value) / (max_value - min_value) * 255
            pixel_array = pixel_array.astype(np.uint8)

            # 创建 PIL Image 对象
            image = Image.fromarray(pixel_array)

            # 保存为 PNG 文件
            png_filename = os.path.splitext(filename)[0] + '.png'
            png_filepath = os.path.join(target_dir, png_filename)
            image.save(png_filepath)