将CT图像转回Dicom格式过程摸索

目标

Dicom作为最常见的医学图像格式,使用非常广泛。将Dicom文件转为jpg、png等图像格式的方法网上有很多。这几天被人问到能不能将图像转回dicom文件,一开始是懵逼状态的。所以目标就是将图像转回Dicom文件,然后就可以用一些专业的Dicom查看软件了。

方式1:用软件

搜索“jpg转Dicom”,出来很多“Diocm转jpg”的结果,还有就是一款软件“JPEG to DICOM”。使用效果如何?转后的Dicom,窗宽窗位变成256和128了。虽然可以定制tag或者使用一个存在的Dicom文件的tag,但是这样一个系列的文件转后就不是一个系列了而且其中的像素值依然是0-255,而不是医学图像常见的0-4095。虽然是一款付费软件,感觉效果不是很随使用者的意思。

方式2:写代码

将Dicom转为JPG的比较简单,pydicom包十几行代码就可以解决了。即使要指定窗宽窗位,代码也不复杂。

背景知识1:CT值与灰度值

CT值的单位是Hounsfield,简称为Hu,范围是-1024-3071。用于衡量人体组织对X射线的吸收率,设定水的吸收率为0Hu。

在DICOM图像读取的过程中,我们会发现图像的像素值通常是0-4096,这是我们常见到的像素值或者灰度值,这就需要我们在图像像素值(灰度值)转换为CT值。

首先,需要读取两个DICOM Tag信息,(0028|1052):rescale intercept和(0028|1053):rescale slope.

然后通过公式计算得到CT值:

Hu = pixel * slope + intercept

背景知识2:CT窗口技术

CT窗口技术指的是将CT值有选择的进行适当的灰阶图像表达,提供最大诊断信息的技术。

  • 窗宽(window width, WW):影响图像的对比度;
  • 窗位(window level, WL):影响图像的亮度;
  • 图像有效显示的CT值范围:窗位-1/2窗宽,窗位+1/2窗宽

开始写代码

传统JPG、PNG图像的灰度值都是0-255,而医学图像的灰度值比较大,是0-4095。那转的时候是不是直接做灰度的线性变换或者非线性变换呢?我一开始也是这么想的,可是尝试线性转换和对数非线性转换转后发现图像的亮度对比度都与静态图像的不同。

了解了背景知识1和背景知识2之后,我们就会知道并不是4096级的灰度都有所显示。肺部CT的WL=-400, WW=1500,所以有效的CT显示范围:[-1150, 350],-1150超出了-1024的范围,但是并不知道是怎么处理了。根据像素值与CT的转换公式可以得到有效的像素范围[-136,1374]。所以我的处理就是将[0,255]映射到[0,1374]。可以发现肉眼观察结果一致。

import pydicom
import cv2
import numpy as np
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import load_img

for i in range(300):
    print(i)
    img = load_img("./"+str(i+1)+".jpg")
        
    data2 = img_to_array(img)
    data2 = cv2.cvtColor(data2,cv2.COLOR_BGR2GRAY)
    data3 = np.array([[data2[i][j]*1374/255 for j in range(512)] for i in range(512)])

    ds = pydicom.dcmread("./"+str(i+1)+".dcm")
    
    data3=data3.astype('int16')
    ds.PixelData = data3.tostring()
    ds.Rows, ds.Columns = data3.shape

    ds.save_as("./"+str(i+1)+".dcm")