草庐IT

使用pyradiomics提取影像组学特征【详细】

fighting_! 2023-04-05 原文

使用pyradiomics提取影像组学特征【详细】

最近由于项目需求要使用pyradiomics提取影像组学特征,网上阅读了很多别人的博客,学到一些,然后去查看了pyradiomics的官方文档,最后自己实现了特征的提取,写下此文记录,方便日后查看。

首先放上官方文档:https://pyradiomics.readthedocs.io/
和pyradiomics源代码地址:https://github.com/AIM-Harvard/pyradiomics

第一步、安装

在已经安装好的Python环境下,执行:

pip install pyradiomics

第二步、提取特征

通过自定义提取特征可以根据自己的需求来设置并提取。

  • 首先,可以指定用于提取特征的图像类型。在pyradiomics包中为我们提供了许多可以使用的滤波器,所以我们可以使用原始图像及经过各种滤波器之后的图像,如下方表格,具体可以参考官方:图像类型
图像类型解释
Original原始图像
Wavelet小波变换。产生在三个维度中每个维度分别使用高通、低通滤波器的所有组合(LLH、LHL、LHH、HLL、HLH、HHL、HHH、LLL)
LoGLaplacian of Gaussian filter高斯滤波器的拉普拉斯算子,是一种边缘增强滤波器。使用它需要指定参数sigma,低 sigma 强调精细纹理,高 sigma 值强调粗糙纹理
Square平方。取原始像素的平方并将它们线性缩放回原始范围
SquareRoot平方根。取绝对图像强度的平方根并将它们缩放回原始范围
Logarithm对数。取绝对强度 + 1 的对数,值缩放到原始范围
Exponential指数。采用e^(绝对强度)获取强度的指数值,值被缩放到原始范围
Gradient梯度。返回局部梯度的大小
LocalBinaryPattern2D在每一片中进行的本地二进制模式
LocalBinaryPattern3D在3d中进行的本地二进制模式

指定方式:设置特征提取器后可以在下边指定(如何设置特征提取器:extractor
可以直接使用:enableAllImageTypes()启用所有类型
也可以使用:enableImageTypeByName( imageType , enabled=True , customArgs=None )启用你想用的类型
例如:

# 所有类型
extractor.enableAllFeatures()
# 指定使用LoG和Wavelet滤波器
extractor.enableImageTypeByName('LoG')
extractor.enableImageTypeByName('Wavelet')
  • 然后可以指定所要提取的特征。pyradiomics包也为我们提供了很多种可选的特征,如下方表格,具体特征类型详细资料可参考:radiomics-features
特征类型特征解释
First Order Features(共19个)Energy能量
Total Energy总能量
Entropy
Minimum最小特征值
10Percentile特征值的百分之10的值
90Percentile特征值得百分之90的值
Maximum最大特征值
Mean均值
Median中位数
InterquartileRange四分位距离
Range灰度值范围
MeanAbsoluteDeviation(MAD)平均绝对误差
RobustMeanAbsoluteDeviation(rMAD) 鲁棒平均绝对偏差
RootMeanSquared(RMS)均方根误差
StandardDeviation标准差。测量平均值的变化或离散量,默认不启用,因为与方差相关
Skewness偏度。测量值的分布关于平均值的不对称性
Kurtosis峰度。是图像 ROI 中值分布的“峰值”的量度
Variance方差。是每个强度值与平均值的平方距离的平均值
Uniformity均匀度。是每个强度值的平方和
特征类型特征解释
Shape Features (3D) (共17个)MeshVolume网格体积
VoxelVolume体素体积
SurfaceArea表面积
SurfaceVolumeRatio表面积体积比
Sphericity球形度
Compactness1紧凑度1。衡量肿瘤形状相对于球形的紧密程度,由于与球形度、紧凑度2、球形不对称相关,默认不启用
Compactness2紧凑度2。衡量肿瘤形状相对于球形的紧密程度,与1的计算公式不同,默认不启用
SphericalDisproportion球形不对称。是肿瘤区域的表面积与与肿瘤区域具有相同体积的球体的表面积之比,是球形度的倒数,默认不启用
Maximum3DDiameter最大3D直径
Maximum2DDiameterSlice最大二维直径(切片),定义为行列(通常是轴向)平面中肿瘤表面网格顶点之间的最大成对欧几里得距离。
Maximum2DDiameterColumn最大2D直径(列)。定义为行切片(通常是冠状)平面中肿瘤表面网格顶点之间的最大成对欧几里得距离。
Maximum2DDiameterRow最大二维直径(行)。定义为列切片(通常为矢状)平面中肿瘤表面网格顶点之间的最大成对欧几里得距离。
MajorAxisLength长轴长度
MinorAxisLength短轴长度
LeastAxisLength最小轴长度
Elongation伸长率。表示ROI形状中两个最大的主成分之间的关系
Flatness平整度。表示ROI形状中最大和最小主成分之间的关系
特征类型特征解释
Shape Features (2D)MeshSurface网格面。由三角形网格定义,计算ROI的表面
PixelSurface像素面。ROI 中的像素数乘以单个像素的表面积
Perimeter周长
PerimeterSurfaceRatio周长比。值越低越紧凑
Sphericity球形度
SphericalDisproportion球形不均匀度。是球形度的倒数 ,与球形度相关,默认不启用
MaximumDiameter最大二维直径。定义为肿瘤表面网格顶点之间的最大成对欧几里得距离
MajorAxisLength长轴长度
MinorAxisLength短轴长度
Elongation伸长率。显示了 ROI 形状中两个最大主成分之间的关​​系
特征类型特征解释
Gray Level Co-occurrence Matrix (GLCM) Features灰度共生矩阵特征(共24个)Autocorrelation自相关。是纹理细度和粗糙度大小的量度
JointAverage联合平均
ClusterProminence集群显著性。衡量 GLCM 偏度和不对称性的指标
ClusterShade集群阴影。衡量 GLCM 偏度和均匀度的指标
ClusterTendency集群趋势
Contrast对比度
Correlation相关性
DifferenceAverage平均差
DifferenceEntropy差分熵
DifferenceVariance差异方差。是异质性的一种度量
Dissimilarity差异性。已弃用
JointEnergy联合能量
JointEntropy联合熵。是邻域强度值的随机性/可变性的度量
Imc1相关性信息度量 (IMC) 1
Imc2相关性信息度量 (IMC) 2
Idm逆差矩
MCC最大相关系数
Idmn逆差分矩归一化
Id逆差
Idn逆差分归一化
InverseVariance逆方差
MaximumProbability最大概率
SumAverage求和平均
SumEntropy总熵
SumSquares平方和
特征类型特征解释
Gray Level Size Zone Matrix (GLSZM) Features灰度级大小区域矩阵特征 (共16个)SmallAreaEmphasis是小尺寸区域分布的量度,数值越大表示区域越小,纹理越精细
LargeAreaEmphasis是大面积区域分布的度量,值越大表示区域越大,纹理越粗糙。
GrayLevelNonUniformity灰度非均匀性。测量图像中灰度级强度值的可变性,值越低表示强度值越均匀。
GrayLevelNonUniformityNormalized灰度非均匀归一化。测量图像中灰度强度值的可变性,值越低表示强度值的相似性越大
SizeZoneNonUniformity尺寸区域非均匀性。测量图像中大小区域体积的可变性,值越低表示大小区域体积越均匀
SizeZoneNonUniformityNormalized尺寸区域非均匀归一化。测量整个图像中大小区域体积的可变性,值越低表示图像中区域大小体积之间的同质性越高
ZonePercentage区域百分比。获取 ROI 中的区域数和体素数的比率来测量纹理的粗糙度
GrayLevelVariance灰度方差
ZoneVariance区域方差
ZoneEntropy区域熵
LowGrayLevelZoneEmphasis低灰度区域强调
HighGrayLevelZoneEmphasis高灰度区域强调
SmallAreaLowGrayLevelEmphasis小面积低灰度区域强调
SmallAreaHighGrayLevelEmphasis小区域高灰度强调
LargeAreaLowGrayLevelEmphasis大面积低灰度强调
LargeAreaHighGrayLevelEmphasis大面积高灰度强调
特征类型特征解释
Gray Level Run Length Matrix (GLRLM) Features灰度游程矩阵 (GLRLM) 特征 (共16个)ShortRunEmphasis是衡量短运行长度分布的指标,值越大表示运行长度越短,纹理纹理越精细。
LongRunEmphasis是对长行程分布的度量,值越大表示行程越长,结构纹理越粗糙。
GrayLevelNonUniformity灰度非均匀性
GrayLevelNonUniformityNormalized灰度非均匀归一化
RunLengthNonUniformity运行长度非均匀性
RunLengthNonUniformityNormalized运行长度非均匀归一化
RunPercentage运行百分比。通过获取 ROI 中的运行次数和体素数的比率来测量纹理的粗糙度
GrayLevelVariance灰度级方差
RunVariance运行方差
RunEntropy运行熵
LowGrayLevelRunEmphasis测量低灰度值的分布,值越高表示图像中低灰度值的集中度越高
HighGrayLevelRunEmphasis测量较高灰度值的分布,值越高表示图像中高灰度值的集中度越高
ShortRunLowGrayLevelEmphasis测量具有较低灰度值的较短运行长度的联合分布
ShortRunHighGrayLevelEmphasis测量具有较高灰度值的较短运行长度的联合分布
LongRunLowGrayLevelEmphasis测量具有较低灰度值的长运行长度的联合分布
LongRunHighGrayLevelEmphasis测量具有较高灰度值的长运行长度的联合分布
特征类型特征解释
Neighbouring Gray Tone Difference Matrix (NGTDM) Features相邻灰度差矩阵(共5个) (NGTDM) 特征Coarseness粗糙度
Contrast对比度
Busyness繁忙度。从像素到其邻居的变化的度量。繁忙度的高值表示“繁忙”图像,像素与其邻域之间的强度快速变化
Complexity复杂度
Strength强度
特征类型特征解释
Gray Level Dependence Matrix (GLDM) Features 灰度依赖矩阵 (GLDM) 特征(共14个)SmallDependenceEmphasis小依赖分布的度量,值越大表示依赖越小,纹理越不均匀
LargeDependenceEmphasis大依赖分布的度量,值越大表示依赖越大,纹理越均匀
GrayLevelNonUniformity灰度非均匀性。测量图像中灰度级强度值的相似性
DependenceNonUniformity衡量整个图像中依赖关系的相似性,值越低表示图像中依赖关系之间的同质性越高
DependenceNonUniformityNormalized依赖非均匀归一化。衡量整个图像中依赖关系的相似性,值越低表示图像中依赖关系之间的同质性越高
GrayLevelVariance灰度方差
DependenceVariance依赖方差
DependenceEntropy依赖熵
LowGrayLevelEmphasis测量低灰度值的分布,值越大表示图像中低灰度值的集中度越高
HighGrayLevelEmphasis测量较高灰度值的分布,值越高表示图像中高灰度值的集中度越高
SmallDependenceLowGrayLevelEmphasis测量具有较低灰度值的小相关性的联合分布
SmallDependenceHighGrayLevelEmphasis测量具有较高灰度值的小相关性的联合分布
LargeDependenceLowGrayLevelEmphasis测量具有较低灰度值的大相关性的联合分布
LargeDependenceHighGrayLevelEmphasis测量具有较高灰度值的大相关性的联合分布

注意:除了形状特征类外,其他特征都可以在原始图像和滤波后的图像上进行计算

具体的指定方法:
可以直接使用:enableAllFeatures( )启用所有类型
也可以使用:enableFeatureClassByName(featureClass, enabled=True)启用你想用的类型
例如:

# 设置一阶特征
extractor.enableFeatureClassByName('firstorder')
# 设置只提取一阶特征的'Mean'和'Skewness'
extractor.enableFeaturesByName(firstorder=['Mean', 'Skewness'])

也可以直接通过特征类别来启用具体的特征,示例见:https://github.com/AIM-Harvard/pyradiomics/blob/master/examples/helloFeatureClass.py

  • 第三步可以对特征提取器进行一些设置。是否对原图归一化、是否重采样,原文档见:feature-extractor-level

图像归一化:

  • normalize:默认为false。设置为true时进行图像归一化。
  • normalizeScale:确定图像归一化后的比例。默认为1。
  • removeOutliers:定义要从图像中删除的异常值。默认为0。

图像/mask重采样:

  • resampledPixelSpacing:设置重采样时的体素大小。默认无。
  • interpolator:设置用于重采样的插值器。仅适用于重采样图像,sitkNearestNeighbor始终用于重采样掩码以保留标签值。可选的插值器:
  • padDistance:设置重采样期间裁剪肿瘤体时的体素补充数量。

例如:

settings = {}
settings['![binWidth](https://img-blog.csdnimg.cn/c9b0896a5eea4eaf8217d0ed7f23e92b.png)
'] = 25
settings['resampledPixelSpacing'] = [3,3,3]  # [3,3,3] is an example for defining resampling (voxels with size 3x3x3mm)
settings['interpolator'] = sitk.sitkBSpline

还有其他的一些设置,根据自己的需要修改即可。
最后举一个完整的例子,我要处理的是CT数据,所以我参考了pyradiomics的github源码中ct参数的设置,最后我的代码如下:

from __future__ import print_function
import six
import os  # needed navigate the system to get the input data
import numpy as np
import radiomics
import pandas as pd
import SimpleITK as sitk
from radiomics import featureextractor  # This module is used for interaction with pyradiomics
import argparse
def catch_features(imagePath,maskPath):
    if imagePath is None or maskPath is None:  # Something went wrong, in this case PyRadiomics will also log an error
        raise Exception('Error getting testcase!')  # Raise exception to prevent cells below from running in case of "run all"
    settings = {}
    settings['binWidth'] = 25  # 5
    settings['sigma'] = [3, 5]
    settings['Interpolator'] = sitk.sitkBSpline
    settings['resampledPixelSpacing'] = [1, 1, 1]  # 3,3,3
    settings['voxelArrayShift'] = 1000  # 300
    settings['normalize'] = True
    settings['normalizeScale'] = 100
    extractor = featureextractor.RadiomicsFeatureExtractor(**settings)
    #extractor = featureextractor.RadiomicsFeatureExtractor()
    print('Extraction parameters:\n\t', extractor.settings)

    extractor.enableImageTypeByName('LoG')
    extractor.enableImageTypeByName('Wavelet')
    extractor.enableAllFeatures()
    extractor.enableFeaturesByName(firstorder=['Energy', 'TotalEnergy', 'Entropy', 'Minimum', '10Percentile', '90Percentile', 'Maximum', 'Mean', 'Median', 'InterquartileRange', 'Range', 'MeanAbsoluteDeviation', 'RobustMeanAbsoluteDeviation', 'RootMeanSquared', 'StandardDeviation', 'Skewness', 'Kurtosis', 'Variance', 'Uniformity'])
    extractor.enableFeaturesByName(shape=['VoxelVolume', 'MeshVolume', 'SurfaceArea', 'SurfaceVolumeRatio', 'Compactness1', 'Compactness2', 'Sphericity', 'SphericalDisproportion','Maximum3DDiameter','Maximum2DDiameterSlice','Maximum2DDiameterColumn','Maximum2DDiameterRow', 'MajorAxisLength', 'MinorAxisLength', 'LeastAxisLength', 'Elongation', 'Flatness'])
# 上边两句我将一阶特征和形状特征中的默认禁用的特征都手动启用,为了之后特征筛选
    print('Enabled filters:\n\t', extractor.enabledImagetypes)
    feature_cur = []
    feature_name = []
    result = extractor.execute(imagePath, maskPath, label=255)
        for key, value in six.iteritems(result):
        print('\t', key, ':', value)
        feature_name.append(key)
        feature_cur.append(value)
    print(len(feature_cur[37:]))
    name = feature_name[37:]
    name = np.array(name)
    '''
    flag=1
    if flag:
        name = np.array(feature_name)
        name_df = pd.DataFrame(name)
        writer = pd.ExcelWriter('key.xlsx')
        name_df.to_excel(writer)
        writer.save()
        flag = 0
    '''
    for i in range(len(feature_cur[37:])):
        #if type(feature_cur[i+22]) != type(feature_cur[30]):
        feature_cur[i+37] = float(feature_cur[i+37])
    return feature_cur[37:],name

image_dir = r'D:\study\extract_radiomics_feature\linshi'
mask_dir = r'D:\study\extract_radiomics_feature\linshi'
patient_list = os.listdir(image_dir)
save_file = np.empty(shape=[1,1051])
id = []
for patient in patient_list:
    print(patient)
    for file in os.listdir(os.path.join(image_dir,patient)):
        if file =='image.nii':
            imagePath = os.path.join(image_dir,patient,file)
        if file =='mask_gtv-1.nii':
            maskPath = os.path.join(mask_dir,patient,file)
    print(imagePath)
    print(maskPath)
    save_curdata,name = catch_features(imagePath,maskPath)
    save_curdata = np.array(save_curdata)
    save_curdata = save_curdata.reshape([1, 1051])
    id.append(patient.split('.')[0])
    np.concatenate((patient,save_curdata),axis=1)
    save_file = np.append(save_file,save_curdata,axis=0)
    print(save_file.shape)
save_file = np.delete(save_file,0,0)
#save_file = save_file.transpose()
#print(save_file.shape)
id_num = len(id)
id = np.array(id)
name_df = pd.DataFrame(save_file)
name_df.index = id
name_df.columns = name
writer = pd.ExcelWriter('NSCLC-Radiomics-features.xlsx')
name_df.to_excel(writer)
writer.save()

最后结果如下:

有关使用pyradiomics提取影像组学特征【详细】的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐