离线
根据[4]中的定义:
CT 的特点是能够分辨人体组织密度的轻微差别,所采用的标准是根据各种组织对X 线的线性吸收系数(μ值) 来决定的。
[5]中提到了一个公式:
所以比赛中的dicom的灰度值需要转化为CT值。
CT值的物理意义就是CT射线照了你的身体,辐射经过你的身体时的辐射强度的衰减程度。
-----------------------------------------------------------------------------------------------------------------------------
[1]中对CT图像的windowing的定义:]
Windowing , also known as grey-level mapping , contrast stretching , histogram modification or contrast enhancement is the process in which the CT image greyscale component of an image is manipulated via the CT numbers; doing this will change the appearance of the picture to highlight particular structures. The brightness of the image is, adjusted via the window level. The contrast is adjusted via the window width.
说白了就是灰度映射为辐射强度 ,然后提高对比度
根据[2],dicom里面,如果给出了intercept和slope,就认为灰度值和辐射强度之间的转化是线性关系.
否则就是非线性关系,是否是线性关系可以根据对dicom的数据读取来判断(下面的代码输出内容中有)
然后是过滤处理资料:
也就是根据Hu(CT)值来筛选我们想要的部位的图片,其他部位全部抹黑或者抹白(对应代码中的img_min或者img_max),目的是为了增加对比度.
下面来自[3]的代码,这个代码是用来进行windowing操作和滤波的:
# Viewing Dicom CT images with correct windowing CT image values correspond to [Hounsfield units](https://en.wikipedia.org/wiki/Hounsfield_scale) (HU). But the values stored in CT Dicoms are not Hounsfield units, but instead a scaled version. To extract the Hounsfield units we need to apply a linear transformation, which can be deduced from the Dicom tags. Once we have transformed the pixel values to Hounsfield units, we can apply a *windowing*: the usual values for a head CT are a center of 40 and a width of 80, but we can also extract this from the Dicom headers. 复制代码 from glob import glob import os import pandas as pd import numpy as np import re from PIL import Image import seaborn as sns from random import randrange #checnking the input files print(os.listdir("../input/rsna-intracranial-hemorrhage-detection/")) ## Load Data #reading all dcm files into train and text train = sorted(glob("../input/rsna-intracranial-hemorrhage-detection/stage_1_train_images/*.dcm")) test = sorted(glob("../input/rsna-intracranial-hemorrhage-detection/stage_1_test_images/*.dcm")) print("train files: ", len(train)) print("test files: ", len(test)) pd.reset_option('max_colwidth') train_df = pd.read_csv('../input/rsna-intracranial-hemorrhage-detection/stage_1_train.csv') def window_image(img, window_center,window_width, intercept, slope): img = (img*slope +intercept)#灰度值转化为CT辐射强度,转化后的结果其实可以理解为"医用像素值" img_min = window_center - window_width//2 # "-"后面的先计算 img_max = window_center + window_width//2 # 下面其实是一个滤波器,过滤掉噪音 img[img<img_min] = img_min img[img>img_max] = img_max return img # 这里的img是一个二维矩阵 def get_first_of_dicom_field_as_int(x): #get x[0] as in int is x is a 'pydicom.multival.MultiValue', otherwise get int(x) if type(x) == pydicom.multival.MultiValue:#如果有很多个值 return int(x[0]) else: return int(x) def get_windowing(data): # 下面是获取dicom数据库中某个图片的各个参数的方式,并不是坐标 dicom_fields = [data[('0028','1050')].value, #window center data[('0028','1051')].value, #window width data[('0028','1052')].value, #intercept data[('0028','1053')].value] #slope # 上面的这个种(0028,1053)在资料中被称为Tag return [get_first_of_dicom_field_as_int(x) for x in dicom_fields] import pydicom #图片数据库 import matplotlib.pyplot as plt print(len(train)) case = 199 # train是个list类型 data = pydicom.dcmread(train[case]) #指定某张照片 plt.imshow(img, cmap=plt.cm.bone) print("-------------------------------------1--------------------------------") window_center , window_width, intercept, slope = get_windowing(data)#从dicom数据库中获取data的参数 #displaying the image img = pydicom.read_file(train[case]).pixel_array img = window_image(img, window_center, window_width, intercept, slope)#windowing操作以及过滤噪声 plt.imshow(img, cmap=plt.cm.bone) plt.grid(False) print("---------------------------------------2------------------------------") print(data) 复制代码 上述代码运行后会输出dicom的信息以及一张颅内图片的预览:
---------------------------------------2------------------------------ (0008, 0018) SOP Instance UID UI: ID_00145de6f (0008, 0060) Modality CS: 'CT' (0010, 0020) Patient ID LO: 'ID_e58c888d' (0020, 000d) Study Instance UID UI: ID_c69165e24e (0020, 000e) Series Instance UID UI: ID_49ed8e3bef (0020, 0010) Study ID SH: '' (0020, 0032) Image Position (Patient) DS: ['-125.000000', '-124.697983', '223.549103'] (0020, 0037) Image Orientation (Patient) DS: ['1.000000', '0.000000', '0.000000', '0.000000', '0.927184', '-0.374607'] (0028, 0002) Samples per Pixel US: 1 (0028, 0004) Photometric Interpretation CS: 'MONOCHROME2' (0028, 0010) Rows US: 512 (0028, 0011) Columns US: 512 (0028, 0030) Pixel Spacing DS: ['0.488281', '0.488281'] (0028, 0100) Bits Allocated US: 16 (0028, 0101) Bits Stored US: 16 (0028, 0102) High Bit US: 15 (0028, 0103) Pixel Representation US: 1 (0028, 1050) Window Center DS: "30" (0028, 1051) Window Width DS: "80" (0028, 1052) Rescale Intercept DS: "-1024" (0028, 1053) Rescale Slope DS: "1" (7fe0, 0010) Pixel Data OW: Array of 524288 elements 复制代码
## Visualize Sample Images
TRAIN_IMG_PATH = "../input/rsna-intracranial-hemorrhage-detection/stage_1_train_images/" TEST_IMG_PATH = "../input/rsna-intracranial-hemorrhage-detection/stage_1_test_images/" def view_images(images, title = '', aug = None): width = 5 height = 2 fig, axs = plt.subplots(height, width, figsize=(15,5)) for im in range(0, height * width): data = pydicom.read_file(os.path.join(TRAIN_IMG_PATH,images[im]+ '.dcm')) image = data.pixel_array window_center , window_width, intercept, slope = get_windowing(data)#从dicom中获取参数 image_windowed = window_image(image, window_center, window_width, intercept, slope) i = im // width j = im % width axs[i,j].imshow(image_windowed, cmap=plt.cm.bone) axs[i,j].axis('off') plt.suptitle(title) plt.show() 复制代码 train_df['image'] = train_df['ID'].str.slice(stop=12)#因为图片名称的前半部分是ID train_df['diagnosis'] = train_df['ID'].str.slice(start=13)#因为图片名称的后半部分是出血类型 print("------------------------------------从下面开始每个类型的图片都看十张------------------------------------------------------") view_images(train_df[(train_df['diagnosis'] == 'epidural') & (train_df['Label'] == 1)][:10].image.values, title = 'Images with epidural') 复制代码
下面代码与上面一句类似,都是浏览图片(结果略)
view_images(train_df[(train_df['diagnosis'] == 'intraparenchymal') & (train_df['Label'] == 1)][:10].image.values, title = 'Images with intraparenchymal') view_images(train_df[(train_df['diagnosis'] == 'intraventricular')& (train_df['Label'] == 1)][:10].image.values, title = 'Images with intraventricular') view_images(train_df[(train_df['diagnosis'] == 'subarachnoid')& (train_df['Label'] == 1)][:10].image.values, title = 'Images with subarachnoid') s'] == 'subdural') & (train_df['Label'] == 1)][:10].image.values, title = 'Images with subarachnoid') 复制代码
Reference:
[1]https://radiopaedia.org/articles/windowing-ct
[2]https://stackoverflow.com/questions/10193971/rescale-slope-and-rescale-intercept
[3]https://www.kaggle.com/omission/eda-view-dicom-images-with-correct-windowing
[4]http://www.xctmr.com/baike/ct/d054abd3bf1a96110b623e4cc2b58575.html
[5]https://baike.baidu.com/item/CT值单位/15635363
来源:https://blog.csdn.net/appleyuchi/article/details/102388184
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!