radiomics.featureextractor-----使用pyradiomics提取2维医学图像及其掩模的特征

1 本篇解决的问题介绍

一般而言都是使用SimpleITK.ReadImage()方法来读取3D的医学图像和掩模,然后再利用pyradiomics中featureextractor来直接提取一阶特征、3D形状特征、小波分解特征等。问题出现了,并不是所有的3D医学图像都是有其对应的3D Mask的,这是因为有些比较细小的3D病变组织可能极其难以手动分割或者自动分割。这导致数据集转化成了这些3D图像的某些侧面的截面图以及对应的2D Mask. (注!这些2D的截面只能保存成为普通的JPG、BMP图像了)

于是

  • SimpleITK可以读取2D的普通格式图像吗?
  • 用于3D特征提取的featureextractor怎么用于2D图片?

2 解决方案详情

  • 可以读取,但是必须转化数据格式为sitk.sitkInt8(经过实际测试,不转换就会报错),但是其实这样是错误的!!!之前笔者一直以为这样能读取出来就是OK的,但是后来在实际调试的时候发现这样从这种方式读取的itkImage在转化成array的时候,读取的array是与使用cv2.imread读取的结果不一致的,这一点大家可以自行测试!个人猜测是因为jpg图像是三通道的,所以这里实际上sitk.ReadImage函数还是把JPG当成了三维医学图像来读取的,所以也猜测sitk的源码很有可能也没有对于图片的类型做类型检查!

后来笔者解决这个问题:1) 首先使用cv2.imread来读取得到正确的array, 然后再利用sitk.GetImageFromArray来得到正确的itkImage类型. 不然的话你会发现在featureextractor里面写上label=255等是会报错的,报错原因是Mask图像找不到这个label对应的像素点,所以说直接使用sitk.ReadImage读取JP图像后得到的Array值是错误的!
2)由于具体问题的需要,在利用sitk.GetImageFromArray函数之前可能需要把三通道的RGB类型的Array转化成灰度Array!比如后续利用featureextractor提取二维的形态特征的时候就需要,如果不将其转化为1通道的灰度Array,会报错提示没有shape2D这个特征!
(备注:这里笔者所说的itkImage只是SimpleIK.SimpleITK.Image类型的缩写)

img_path = r'D:\10.jpg'
mask_path = r'D:\10_mask.jpg'
img = sitk.ReadImage(img_path, sitk.sitkInt8)
mask = sitk.ReadImage(mask_path, sitk.sitkInt8)

在这里插入图片描述

    img2d_arr = cv2.imread(img_path)
    mask2d_arr = cv2.imread(mask_path)
    print("min 0:", np.min(mask2d_arr))
    print("max 0:", np.max(mask2d_arr))

    img2d_gray_arr = cv2.cvtColor(img2d_arr, cv2.COLOR_BGR2GRAY)
    mask2d_gray_arr = cv2.cvtColor(mask2d_arr, cv2.COLOR_BGR2GRAY)
    print("min 1:", np.min(mask2d_gray_arr))
    print("max 1:", np.max(mask2d_gray_arr))
    image2d = sitk.GetImageFromArray(img2d_gray_arr)
    mask2d = sitk.GetImageFromArray(mask2d_gray_arr)

    mask2d_trans = sitk.GetArrayFromImage(mask2d)
    print("min:", np.min(mask2d_trans))
    print("max:", np.max(mask2d_trans))
    print("equal:", np.all(mask2d_trans == mask2d_gray_arr))

    img_name = os.path.basename(img_path)

    settings = {
        'binWidth': 20,
        'sigma': [1, 2, 3],
        'verbose': True,
        # 'force2D': True,
        'label': 255
    }
    extractor = featureextractor.RadiomicsFeatureExtractor(additionInfo=True, **settings)
    extractor.enableImageTypeByName('LoG')
    extractor.enableImageTypeByName('LBP2D')
    extractor.enableImageTypeByName('Wavelet')
    extractor.enableFeatureClassByName('shape2D')
    result = extractor.execute(image2d, mask2d)
    print("result length: ", len(result))
  • 需要在参数里显示设置force2D=True,这时候‘’log-sigma-1-mm-3D_glrlm_ShortRunEmphasis’这种尽管名字中含有3D的LOG特征仍然会保留,但是四种小波图像LL、LH、HL、HH对应的特征变成只有L和H两种了,
import radiomics

settings = {
        'binWidth': 20,
        'sigma': [1, 2, 3],
        'verbose': True,
         'force2D’: True,
    }
 extractor = radiomics.featureextractor.RadiomicsFeatureExtractor(additionInfo=True, **settings)

3 关于特征提取的其他注意事项

  • 使用radiomics.featureextractor.RadiomicsFeatureExtractor能够提取到很多类型的特征,但是提取的shape2D只有9个特征,缺少了一个Spherical Disproportion
extractor.enableAllFeatures()
  • radiomics.featureextractor.RadiomicsFeatureExtractor的初始化方式可以不提供任何参数,也可以提供settings字典;获取特征要使用extractor.excute(img,mask), 注意在这里传入图片和掩膜,而不是在初始化里面
  • 注意设置的滤波类型及参数设置对特征数目的影响
settings = {
        'binWidth': 20,
        'sigma': [1, 2, 3],
        'verbose': True,
         'force2D’: True,
    }
extractor = featureextractor.RadiomicsFeatureExtractor(additionInfo=True, **settings)
extractor.enableImageTypeByName('LoG')     # 即使设置了LoG,但是没有设置sigma的值不会计算该特征
extractor.enableImageTypeByName('LBP2D')    # 无需其他参数  93个特征
extractor.enableImageTypeByName('Wavelet')  # 默认情况下就有LL,LH, HL,HH四种滤波 4 * 93 个特征
extractor.enableFeatureClassByName('shape2D') # 必须得设置参数
  • 也可以使用专门类别的特征提取器来提取特征,比如firstorder.RadiomicsFirstOrder, 但是这些初始化的时候提供图片和掩膜,而在execute时不需要
from radiomics import firstorder, featureextractor
from radiomics import shape2D
import cv2
import SimpleITK as sitk

img_path = r'D:\10.jpg'
mask_path = r'D:\10_mask.jpg'
img = sitk.ReadImage(img_path, sitk.sitkInt8)
mask = sitk.ReadImage(mask_path, sitk.sitkInt8)

settings = {'force2D': True}
firstOrderFeatures = firstorder.RadiomicsFirstOrder(img, mask, **settings)
firstOrderFeatures.enableAllFeatures() # On the feature class level, all features are disabled by default.
firstOrderFeatures.execute()
print(dir(firstOrderFeatures))
print(firstOrderFeatures.getEnergyFeatureValue())
print(firstOrderFeatures.getTotalEnergyFeatureValue())
print(firstOrderFeatures.getEntropyFeatureValue())


shape2DFeatures = shape2D.RadiomicsShape2D(img, mask, **settings)
print(dir(shape2DFeatures))
shape2DFeatures.execute()
shape2DFeatures.enableAllFeatures()
print(shape2DFeatures.getElongationFeatureValue())
print(shape2DFeatures.getMeshSurfaceFeatureValue())
print(shape2DFeatures.getMajorAxisLengthFeatureValue())
print(shape2DFeatures.getMaximumDiameterFeatureValue())
  • **注意这里mask的含义! mask指的是感兴趣区ROI的Mask,而不能是其他分割Mask!**笔者的一个项目中是将矩形的ROI从原图提取出来了之后,然后对这个ROI的某种成分再有一个分割结果m,当时作者是将ROI和这个分割结果m传进函数extractor.execute(image2d, mask2d)中,但是部分ROI并没有该成分导致分割结果为全黑,该函数报错!正确的mask是用全白图片作为分割结果,因为ROI图片整张都是感兴趣区域!
    radiomics.featureextractor-----使用pyradiomics提取2维医学图像及其掩模的特征_第1张图片 原始这个函数是针对三维医学图像的,而三维图像有相当大比例的全黑背景,所以其Mask对于提取三维医学图像的特征是不可缺少的!而对于二维图像既可以传入原图 和 原图ROI的mask, 也可以像我这里这样使用提取后的ROI 和全白的mask, 如果原图中每个ROI的大小不一致,使用后者更好,如果一致使用前者更好。

  • 提取特征数目不对但是不报错:radiomics.featureextractor-----使用pyradiomics提取2维医学图像及其掩模的特征_第2张图片
    radiomics.featureextractor-----使用pyradiomics提取2维医学图像及其掩模的特征_第3张图片

你可能感兴趣的:(代码,pyradiomics)