医工互联

 找回密码
 注册[Register]

手机动态码快速登录

手机号快速登录

微信登录

微信扫一扫,快速登录

QQ登录

只需一步,快速开始

查看: 258|回复: 0
收起左侧

CT流程与CT图像的windowing操作(转载+整理)

[复制链接]

  离线 

发表于 2023-5-4 06:08:49 | 显示全部楼层 |阅读模式 <
根据[4]中的定义:
  CT 的特点是能够分辨人体组织密度的轻微差别,所采用的标准是根据各种组织对X 线的线性吸收系数(μ值) 来决定的。
[5]中提到了一个公式:
1.jpeg
2.jpeg

所以比赛中的dicom的灰度值需要转化为CT值。
CT值的物理意义就是CT射线照了你的身体,辐射经过你的身体时的辐射强度的衰减程度。
-----------------------------------------------------------------------------------------------------------------------------
[1]中对CT图像的windowing的定义:]
Windowing, also known as grey-level mappingcontrast stretchinghistogram 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的数据读取来判断(下面的代码输出内容中有)
 
然后是过滤处理资料:
CT流程与CT图像的windowing操作(转载+整理)4293 作者:残酷的温柔 帖子ID:28293 CT流程,CT图像,windowing操作,CT值,灰度映射
                               
登录/注册后可看大图

 
也就是根据Hu(CT)值来筛选我们想要的部位的图片,其他部位全部抹黑或者抹白(对应代码中的img_min或者img_max),目的是为了增加对比度.
 
下面来自[3]的代码,这个代码是用来进行windowing操作和滤波的:
 
  1. # Viewing Dicom CT images with correct  windowing
  2. CT image values correspond to [Hounsfield units](https://en.wikipedia.org/wiki/Hounsfield_scale) (HU).  
  3. But the values stored in CT Dicoms are not Hounsfield units,
  4. but instead a scaled version.  
  5. To extract the Hounsfield units we need to apply a linear transformation,
  6. which can be deduced from the Dicom tags.
  7. Once we have transformed the pixel values to Hounsfield units, we can apply a *windowing*:
  8. 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.
复制代码
  1. from glob import glob
  2. import os
  3. import pandas as pd
  4. import numpy as np
  5. import re
  6. from PIL import Image
  7. import seaborn as sns
  8. from random import randrange
  9. #checnking the input files
  10. print(os.listdir("../input/rsna-intracranial-hemorrhage-detection/"))
  11. ## Load Data
  12. #reading all dcm files into train and text
  13. train = sorted(glob("../input/rsna-intracranial-hemorrhage-detection/stage_1_train_images/*.dcm"))
  14. test = sorted(glob("../input/rsna-intracranial-hemorrhage-detection/stage_1_test_images/*.dcm"))
  15. print("train files: ", len(train))
  16. print("test files: ", len(test))
  17. pd.reset_option('max_colwidth')
  18. train_df = pd.read_csv('../input/rsna-intracranial-hemorrhage-detection/stage_1_train.csv')
  19. def window_image(img, window_center,window_width, intercept, slope):
  20.     img = (img*slope +intercept)#灰度值转化为CT辐射强度,转化后的结果其实可以理解为"医用像素值"
  21.     img_min = window_center - window_width//2 # "-"后面的先计算
  22.     img_max = window_center + window_width//2
  23. #     下面其实是一个滤波器,过滤掉噪音
  24.     img[img<img_min] = img_min
  25.     img[img>img_max] = img_max
  26.     return img
  27. # 这里的img是一个二维矩阵
  28. def get_first_of_dicom_field_as_int(x):
  29.     #get x[0] as in int is x is a 'pydicom.multival.MultiValue', otherwise get int(x)
  30.     if type(x) == pydicom.multival.MultiValue:#如果有很多个值
  31.         return int(x[0])
  32.     else:
  33.         return int(x)
  34. def get_windowing(data):
  35. #     下面是获取dicom数据库中某个图片的各个参数的方式,并不是坐标
  36.     dicom_fields = [data[('0028','1050')].value, #window center
  37.                     data[('0028','1051')].value, #window width
  38.                     data[('0028','1052')].value, #intercept
  39.                     data[('0028','1053')].value] #slope
  40. #     上面的这个种(0028,1053)在资料中被称为Tag
  41.     return [get_first_of_dicom_field_as_int(x) for x in dicom_fields]
  42. import pydicom
  43. #图片数据库
  44. import matplotlib.pyplot as plt
  45. print(len(train))
  46. case = 199
  47. # train是个list类型
  48. data = pydicom.dcmread(train[case]) #指定某张照片
  49. plt.imshow(img, cmap=plt.cm.bone)
  50. print("-------------------------------------1--------------------------------")
  51. window_center , window_width, intercept, slope = get_windowing(data)#从dicom数据库中获取data的参数
  52. #displaying the image
  53. img = pydicom.read_file(train[case]).pixel_array
  54. img = window_image(img, window_center, window_width, intercept, slope)#windowing操作以及过滤噪声
  55. plt.imshow(img, cmap=plt.cm.bone)
  56. plt.grid(False)
  57. print("---------------------------------------2------------------------------")
  58. print(data)
复制代码
上述代码运行后会输出dicom的信息以及一张颅内图片的预览:
  1. ---------------------------------------2------------------------------
  2. (0008, 0018) SOP Instance UID                    UI: ID_00145de6f
  3. (0008, 0060) Modality                            CS: 'CT'
  4. (0010, 0020) Patient ID                          LO: 'ID_e58c888d'
  5. (0020, 000d) Study Instance UID                  UI: ID_c69165e24e
  6. (0020, 000e) Series Instance UID                 UI: ID_49ed8e3bef
  7. (0020, 0010) Study ID                            SH: ''
  8. (0020, 0032) Image Position (Patient)            DS: ['-125.000000', '-124.697983', '223.549103']
  9. (0020, 0037) Image Orientation (Patient)         DS: ['1.000000', '0.000000', '0.000000', '0.000000', '0.927184', '-0.374607']
  10. (0028, 0002) Samples per Pixel                   US: 1
  11. (0028, 0004) Photometric Interpretation          CS: 'MONOCHROME2'
  12. (0028, 0010) Rows                                US: 512
  13. (0028, 0011) Columns                             US: 512
  14. (0028, 0030) Pixel Spacing                       DS: ['0.488281', '0.488281']
  15. (0028, 0100) Bits Allocated                      US: 16
  16. (0028, 0101) Bits Stored                         US: 16
  17. (0028, 0102) High Bit                            US: 15
  18. (0028, 0103) Pixel Representation                US: 1
  19. (0028, 1050) Window Center                       DS: "30"
  20. (0028, 1051) Window Width                        DS: "80"
  21. (0028, 1052) Rescale Intercept                   DS: "-1024"
  22. (0028, 1053) Rescale Slope                       DS: "1"
  23. (7fe0, 0010) Pixel Data                          OW: Array of 524288 elements
复制代码
CT流程与CT图像的windowing操作(转载+整理)6491 作者:残酷的温柔 帖子ID:28293 CT流程,CT图像,windowing操作,CT值,灰度映射
                               
登录/注册后可看大图

## Visualize Sample Images
  1. TRAIN_IMG_PATH = "../input/rsna-intracranial-hemorrhage-detection/stage_1_train_images/"
  2. TEST_IMG_PATH = "../input/rsna-intracranial-hemorrhage-detection/stage_1_test_images/"
  3. def view_images(images, title = '', aug = None):
  4.     width = 5
  5.     height = 2
  6.     fig, axs = plt.subplots(height, width, figsize=(15,5))
  7.    
  8.     for im in range(0, height * width):
  9.         data = pydicom.read_file(os.path.join(TRAIN_IMG_PATH,images[im]+ '.dcm'))
  10.         image = data.pixel_array
  11.         window_center , window_width, intercept, slope = get_windowing(data)#从dicom中获取参数
  12.         image_windowed = window_image(image, window_center, window_width, intercept, slope)
  13.         i = im // width
  14.         j = im % width
  15.         axs[i,j].imshow(image_windowed, cmap=plt.cm.bone)
  16.         axs[i,j].axis('off')
  17.         
  18.     plt.suptitle(title)
  19.     plt.show()
复制代码
  1. train_df['image'] = train_df['ID'].str.slice(stop=12)#因为图片名称的前半部分是ID
  2. train_df['diagnosis'] = train_df['ID'].str.slice(start=13)#因为图片名称的后半部分是出血类型
  3. print("------------------------------------从下面开始每个类型的图片都看十张------------------------------------------------------")
  4. view_images(train_df[(train_df['diagnosis'] == 'epidural') & (train_df['Label'] == 1)][:10].image.values, title = 'Images with epidural')
复制代码
CT流程与CT图像的windowing操作(转载+整理)8058 作者:残酷的温柔 帖子ID:28293 CT流程,CT图像,windowing操作,CT值,灰度映射
                               
登录/注册后可看大图

 
下面代码与上面一句类似,都是浏览图片(结果略)
  1. view_images(train_df[(train_df['diagnosis'] == 'intraparenchymal') & (train_df['Label'] == 1)][:10].image.values, title = 'Images with intraparenchymal')
  2. view_images(train_df[(train_df['diagnosis'] == 'intraventricular')& (train_df['Label'] == 1)][:10].image.values, title = 'Images with intraventricular')
  3. view_images(train_df[(train_df['diagnosis'] == 'subarachnoid')& (train_df['Label'] == 1)][:10].image.values, title = 'Images with subarachnoid')
  4. 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
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

提醒:禁止复制他人回复等『恶意灌水』行为,违者重罚!
您需要登录后才可以回帖 登录 | 注册[Register] 手机动态码快速登录 微信登录

本版积分规则

发布主题 快速回复 收藏帖子 返回列表 客服中心 搜索
简体中文 繁體中文 English 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french

QQ|RSS订阅|小黑屋|处罚记录|手机版|联系我们|Archiver|医工互联 |粤ICP备2021178090号 |网站地图

GMT+8, 2024-12-22 16:30 , Processed in 0.260060 second(s), 66 queries .

Powered by Discuz!

Copyright © 2001-2023, Discuz! Team.

快速回复 返回顶部 返回列表