目录
在上一篇文章中影像组学入门1,主要介绍了组学和pyradiomics的大致概念以及实现了一个最简单的代码(用pyradiomics进行组学特征提取并输出结果)。接下来这篇,我们主要讲,如何在之前的基础上使用分类器训练模型,实现图像分类。
分类器是什么
- 在已有数据的基础上学会一个分类函数或构造出一个分类模型
- 比如说SVM(支持向量机),贝叶斯,k临近法,这些都是分类器
- 分类器作用是在标记好类别的训练数据基础上,判断一个新的观察样本所属的类别
分类器实施步骤
- 选定样本(包含正样本和负样本),将所有样本分成训练样本和测试样本两部分。
- 在训练样本上执行分类器算法,生成分类模型。
- 在测试样本上执行分类模型,生成预测结果。
- 根据预测结果,计算必要的评估指标,评估分类模型的性能。
掩模图像是什么
- 在图像处理和计算机视觉领域,是一种用于标记或指示图像中感兴趣区域的二进制图像。它通常与原始图像配对使用,用于指示哪些像素属于感兴趣的目标或区域(并不是标签,只是突出想要特征的位置)。
- 掩模图像的像素值通常为0和1,其中0表示背景或非感兴趣区域,1表示目标或感兴趣区域。通过将掩模图像与原始图像进行逐像素运算,可以提取出感兴趣区域的特征或进行区域标记。
Kmeans是什么
- 是一种聚类方法,也是一种无监督学习方法,不需要样本标签就可以实现,结果取决于所选的特征和聚类参数
- 但准确度不如监督类算法,初始 k 值是什么很重要,需人为确定初始聚类中心
数据集准备
和上一篇用的数据集不同,这一次的数据集长这样,使用的是 nii.gz 后缀的,一个origin图像对应一个masks图像,一共n个样本,我删到了6个
但后文展示的,是使用两个样本的情况,6个样本都用的话需要在服务器上跑,要不太慢了
项目结构
正文开始,敲代码
特征提取
大致代码和上一篇中的相似,有区别的是如下几点
1. 由于数据增多,需要使用循环来拿到多个 ori_path 和 mas_path 的值
for file_origin in files:
print(file_origin)
# 将origin目录下的所有文件名称,用“.nii”切开,取第0位的值
keyword = file_origin.split(".nii")[0]
# 用keyword作为关键字,与masks目录下的文件名称进行匹配
# 获取masks目录中的所有文件
found_files = os.listdir(file_path_masks)
# 列表推导式筛选包含关键字的文件
file_masks_all = [file for file in found_files if keyword in file]
# 如果目录中存在包含该关键字的文件:
if file_masks_all:
for file_masks in file_masks_all:
print(file_masks)
# 分别赋值
ori_path = os.path.join(file_path_origin, file_origin)
mas_path = os.path.join(file_path_masks, file_masks)
print("原始图像路径",ori_path)
print("掩模图像路径",mas_path)
2. 修改一下csv文件的保存方式(行列分别是什么),方便后续对数据进行处理
# 创建一个字典,用于存储特征和值
feature_values = {'name': os.path.basename(file_origin)}
# 选择特定特征并将其保存到 CSV 文件中
# 假设只想保存 'original_shape_VoxelVolume' 和 'original_glcm_Correlation' 这两个特征
selected_features = ['original_shape_VoxelVolume', 'original_glcm_Correlation']
# 遍历所有样本的特征
for key, value in result.items():
# 如果当前特征是所选特征之一,则将其添加到 DataFrame
if key in selected_features:
# 将特征和值添加到字典中
feature_values[key] = value
# 将字典添加到 DataFrame 中
df = pd.concat([df, pd.DataFrame(feature_values, index=[0])], ignore_index=True)
# 调整列的顺序,使 Feature 列在第一列
df = df[['name'] + selected_features]
效果如图所示
进行分类
由于我们数据只有没有标签图像,所以可以考虑使用无监督学习方法中的 k-means聚类 来实现
由于我们只有两个样本,所以对应的聚类的簇数只能是2
# 加载CSV文件
data = pd.read_csv(output_path)
# 提取特征列,selected_features是选择的特征序列
features = data[selected_features].values
# 设置聚类的簇数
k = 2
# 创建K-means模型
kmeans = KMeans(n_clusters=k)
# 训练模型并进行聚类
kmeans.fit(features)
# 获取聚类结果
labels = kmeans.labels_
# 将聚类结果添加到DataFrame
data['Cluster'] = labels
# 保存带有聚类结果的CSV文件
clustered_output_path = 'data/pyradiomics/csv/clustered_features.csv'
data.to_csv(clustered_output_path, index=False)
print("聚类结果已保存")
效果展示(csv文件)
数据可视化
这步就是把刚刚聚好的类用散点图展示出来
import matplotlib.pyplot as plt
# 假设已经进行了聚类并得到了标签
labels = kmeans.labels_
# 假设您的数据是二维的,可以直接使用其中的两个特征进行绘图
feature1 = df['original_shape_VoxelVolume']
feature2 = df['original_glcm_Correlation']
# 绘制散点图
plt.scatter(feature1, feature2, c=labels)
plt.xlabel('original_shape_VoxelVolume')
plt.ylabel('original_glcm_Correlation')
plt.title('Clustering Result')
plt.show()
效果展示
紫色一类,黄色一类,且它们之间距离相差较远,聚类效果还可以
完整代码
from radiomics import featureextractor as FEE
import os
import pandas as pd
import SimpleITK as sitk
from sklearn.cluster import KMeans
file_path_origin = 'data/pyradiomics/nii/origin'
file_path_masks = 'data/pyradiomics/nii/masks'
para_path = 'data/pyradiomics/Params.yaml'
# 使用配置文件初始化特征抽取器
extractor = FEE.RadiomicsFeatureExtractor(parameter_file=para_path)
# 打印抽取器的参数、启用的滤波器和启用的特征
print("Extraction parameters:\n\t", extractor.settings)
print("Enabled filters:\n\t", extractor.enabledImagetypes)
print("Enabled features:\n\t", extractor.enabledFeatures)
# 创建一个空的 DataFrame,用于存储特征数据
df = pd.DataFrame(columns=['name', 'Value'])
for root, dirs, files in os.walk(file_path_origin):
ori_path = None
mas_path = None
print(root)
print(dirs)
print(files)
for file_origin in files:
print(file_origin)
# 将origin目录下的所有文件名称,用“.nii”切开,取第0位的值
keyword = file_origin.split(".nii")[0]
# 用keyword作为关键字,与masks目录下的文件名称进行匹配
# 获取masks目录中的所有文件
found_files = os.listdir(file_path_masks)
# 列表推导式筛选包含关键字的文件
file_masks_all = [file for file in found_files if keyword in file]
# 如果目录中存在包含该关键字的文件:
if file_masks_all:
for file_masks in file_masks_all:
print(file_masks)
# 分别赋值
ori_path = os.path.join(file_path_origin, file_origin)
mas_path = os.path.join(file_path_masks, file_masks)
print("原始图像路径",ori_path)
print("掩模图像路径",mas_path)
# 抽取特征
image = sitk.ReadImage(ori_path)
image1 = sitk.ReadImage(mas_path)
result = extractor.execute(image, image1)
# 输出特征
for key, value in result.items():
print("\t", key, ":", value)
# 创建一个字典,用于存储特征和值
feature_values = {'name': os.path.basename(file_origin)}
# 选择特定特征并将其保存到 CSV 文件中
# 假设你只想保存 'original_shape_Volume' 和 'glcm_Correlation' 这两个特征
selected_features = ['original_shape_VoxelVolume', 'original_glcm_Correlation']
# 遍历所有样本的特征
for key, value in result.items():
# 如果当前特征是所选特征之一,则将其添加到 DataFrame
if key in selected_features:
# 将特征和值添加到字典中
feature_values[key] = value
# 将字典添加到 DataFrame 中
# df = df.append(feature_values, ignore_index=True)
df = pd.concat([df, pd.DataFrame(feature_values, index=[0])], ignore_index=True)
# 调整列的顺序,使 Feature 列在第一列
df = df[['name'] + selected_features]
# 清空,进行下一次遍历
ori_path = None
mas_path = None
# 指定保存到的 CSV 文件路径
output_path = 'data/pyradiomics/csv/selected_features.csv'
# 将 DataFrame 保存为 CSV 文件
df.to_csv(output_path, index=False)
print("已保存")
# 聚类
# 加载CSV文件
data = pd.read_csv(output_path)
# 提取特征列,selected_features是选择的特征序列
features = data[selected_features].values
# 设置聚类的簇数
k = 2
# 创建K-means模型
kmeans = KMeans(n_clusters=k)
# 训练模型并进行聚类
kmeans.fit(features)
# 获取聚类结果
labels = kmeans.labels_
# 将聚类结果添加到DataFrame
data['Cluster'] = labels
# 保存带有聚类结果的CSV文件
clustered_output_path = 'data/pyradiomics/csv/clustered_features.csv'
data.to_csv(clustered_output_path, index=False)
print("聚类结果已保存")
import matplotlib.pyplot as plt
# 假设已经进行了聚类并得到了标签
labels = kmeans.labels_
# 假设您的数据是二维的,可以直接使用其中的两个特征进行绘图
feature1 = df['original_shape_VoxelVolume']
feature2 = df['original_glcm_Correlation']
# 绘制散点图
plt.scatter(feature1, feature2, c=labels)
plt.xlabel('original_shape_VoxelVolume')
plt.ylabel('original_glcm_Correlation')
plt.title('Clustering Result')
plt.show()
效果展示(控制台)
........
.....