一般而言都是使用SimpleITK.ReadImage()方法来读取3D的医学图像和掩模,然后再利用pyradiomics中featureextractor来直接提取一阶特征、3D形状特征、小波分解特征等。问题出现了,并不是所有的3D医学图像都是有其对应的3D Mask的,这是因为有些比较细小的3D病变组织可能极其难以手动分割或者自动分割。这导致数据集转化成了这些3D图像的某些侧面的截面图以及对应的2D Mask. (注!这些2D的截面只能保存成为普通的JPG、BMP图像了)
于是:
后来笔者解决这个问题: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))
import radiomics
settings = {
'binWidth': 20,
'sigma': [1, 2, 3],
'verbose': True,
'force2D’: True,
}
extractor = radiomics.featureextractor.RadiomicsFeatureExtractor(additionInfo=True, **settings)
extractor.enableAllFeatures()
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') # 必须得设置参数
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图片整张都是感兴趣区域!
原始这个函数是针对三维医学图像的,而三维图像有相当大比例的全黑背景,所以其Mask对于提取三维医学图像的特征是不可缺少的!而对于二维图像既可以传入原图 和 原图ROI的mask, 也可以像我这里这样使用提取后的ROI 和全白的mask, 如果原图中每个ROI的大小不一致,使用后者更好,如果一致使用前者更好。