存储网站建设,域名申请注册的步骤,泉州市网站建设,企业网站标题设置目录
一. 语义分割
二. 数据集
三. 数据增强
图像数据处理步骤
CT图像增强方法 #xff1a;windowing方法
直方图均衡化
获取掩膜图像深度
在肿瘤CT图中提取肿瘤
保存肿瘤数据 四. 数据加载
数据批处理
编辑编辑
数据集加载 五. UNet神经网络模型搭建 单张图片…目录
一. 语义分割
二. 数据集
三. 数据增强
图像数据处理步骤
CT图像增强方法 windowing方法
直方图均衡化
获取掩膜图像深度
在肿瘤CT图中提取肿瘤
保存肿瘤数据 四. 数据加载
数据批处理
编辑编辑
数据集加载 五. UNet神经网络模型搭建 单张图片预测图 一. 语义分割
第三代图像分割语义分割 图像分割Image Segmentation)是计算机视觉领域中的一项重要基础技术。图像分割是将数字图像细分为多个图像子区域的过程通过简化或改变图像的表示形式让图像能够更加容易被理解。更简单地说图像分割就是为数字图像中的每一个像素附加标签使得具有相同标签的像素具有某种共同的视觉特性。 医学图像的模态格式更加多样化如X-ray、CT、MRI以及超声等等当然也包括一些常见的RGB图像(如眼底视网膜图像。不同模态图像反应的信息侧重点是不一样的。比如X-ray观察骨骼更清晰CT可以反应组织和器官出血MRI适合观察软组织。而且不同型号的成像设备得到的成像结果有一定差异。 一图为一肝脏CT图像切片可视化结果已经过预处理转化为灰度图像组织与器官之间的分界线比较模糊。
二图为不同个体的肝脏CT图像差异巨大这给肝脏组织提取带来了很大的困难。
二. 数据集 3D-IRCADb (3D Image Reconstruction for Comparison of Algorithm Database用于算法数据库比较的三维图像重建)数据库由75%病例中10名女性和10名男性肝脏肿瘤患者的CT扫描组成每个文件夹对应不同的病人提供了有关图像的信息如肝脏大小宽度、深度、高度或根据Couninurd分割的肿瘤位置。它还表明由于与邻近器官的接触、肝脏的非典型形状或密度甚至图像中的伪影肝脏分割可能会遇到重大困难。
链接https://pan.baidu.com/s/1P76AF-wvrFjElc6tR82tRA 提取码5el7
三. 数据增强
图像数据处理步骤
1.数据加载
2.CT图像增强
3.直方图均衡化增强
4.获取肿瘤对应CT图、肝脏肿瘤掩模图
5.保存图像
DICOM数据读取
使用pydicom库读取文件pydicom.dcmread函数读取文件对文件排序pixel_array属性提取图像像素信息展示图片 批量数据读取
# 批量读取数据
img_slices [pydicom.dcmread(os.path.join(data_path, file_name)) for file_name in os.listdir(data_path)]
os.listdir(data_path)
# 排序避免CT图乱序
img_slices.sort(keylambda x:x.InstanceNumber) # 顺序属性
img_array np.array([i.pixel_array for i in img_slices]) # 提取像素值CT图像增强方法 windowing方法
CT图像的范围很大导致了对比度很差需要针对具体的器官进行处理。
CT值的物理意义就是CT射线照了你的身体辐射经过你的身体时的辐射强度的衰减程度。
CT 的特点是能够分辨人体组织密度的轻微差别所采用的标准是根据各种组织对x线的线性吸收系数μ值来决定的。 根据HuCT值来筛选我们想要的部位的图片其他部位全部抹黑或者抹白目的是为了增加图像对比度。使用windowing方法。观察的CT值范围:窗宽。观察的中心CT值即为窗位然后对肿瘤部分进行二值化处理。
def windowing(img, window_width, window_center):# params:需要增强的图片, 窗口宽度, 窗中心 通过窗口最小值来线性移动窗口增强min_windows float(window_center)-0.5*float(window_width)new_img (img-min_windows)/float(window_width)new_img[new_img0] 0 # 二值化处理 抹白new_img[new_img1] 1 # 抹黑return (new_img * 255).astype(uint8) # 把数据整理成标准图像格式
img_ct windowing(img_array, 500, 150)直方图均衡化
直方图均衡化函数把整个图像分成许多小块(比如按10*10作为一个小块)对每个小块进行均衡化。主要对于图像直方图不是那么单一的(比如存在多峰情况图像比较实用。0pencv中将这种方法为cv2.createCLAHE()
def clahe_equalized(imgs):# 输入imgs的形状必须是3维assert (len(imgs.shape) 3)# 定义均衡化函数clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8))# 新数组存放均衡化后的数据img_res np.zeros_like(imgs)for i in range(len(imgs)):img_res[i,:,:] clahe.apply(np.array(imgs[i,:,:], dtypenp.uint8))return img_res/255plt.hist(img_array.reshape(-1,),bins50) # 降成一维分成50分 获取掩膜图像深度
为加快训练速度自定义函数实现提取肝脏肿瘤对应的CT图像处理后和对应的掩模图并分别保存到不同的文件夹中分别作为模型的输入与输出。读取肿瘤CT图
tumor_slice [pydicom.dcmread(os.path.join(data_path_mask, file_name)) for file_name in os.listdir(data_path_mask)]
#避免CT图乱序,顺序属性
tumor_slice.sort(keylambda x: x.InstanceNumber)
#提取像素值
tumor_array np.array([i.pixel_array for i in tumor_slice])
print(tumor_array.shape) # (129, 512, 512)白色部分为肿瘤掩模图黑色部分对应的像素数组全为0。
在肿瘤CT图中提取肿瘤
index [i.sum() 0 for i in tumor_array] # 提取含肿瘤部分
# print(len(index)) # tumor_array.shape[0] 129
# 提取掩模图的肿瘤部分
img_tumor tumor_array[index]
# 对增强后的CT图提取肿瘤部分
img_patient img_clahe[index]保存肿瘤数据
# 设置保存文件路径
patient_save_path rE:/datasets/liver/tmp/patient/
tumor_save_path rE:/datasets/liver/tmp/tumor/
for path in [patient_save_path, tumor_save_path]:if os.path.exists(path): # 判断文件夹是否存在shutil.rmtree(path) # 清空os.mkdir(path)
# 保留一个肿瘤的数据
# plt.imsave(os.path.join(patient_save_path, 0.jpg), img_patient[0],cmapgray)
for i in range(len(img_patient)):plt.imsave(os.path.join(patient_save_path, f{i}.jpg), img_patient[i], cmapgray)plt.imsave(os.path.join(tumor_save_path, f{i}.jpg), img_tumor[i], cmapgray) 四. 数据加载
数据批处理
取3dircadb1文件夹中数据作为实验对象取前1-10个病人的数据作为训练样本10-20个病人的数据作为测试样本。
1.读取CT图图像片段2.提取像素值3.CT图增强、均衡化4.处理肿瘤掩模图5.对每个病人的肿瘤图进行排序提取肿瘤片段像素值6.提取肿瘤肿瘤部分像素编号7.找到CT图中对应位置8.保存所有肿瘤数据
def processImage(start, end):for num in range(start, end):print(正在处理第%d号病人 % num)data_path frG:/dataPack/基于深度学习的肝脏肿瘤图像分割/3dircadb1/3dircadb1.{num}/PATIENT_DICOM# 读取CT图图像片段image_slices [pydicom.dcmread(os.path.join(data_path, file_name)) for file_name in os.listdir(data_path)]os.listdir(data_path)image_slices.sort(keylambda x: x.InstanceNumber) # 排序# 提取像素值image_array np.array([i.pixel_array for i in image_slices])# CT图增强-windowingimg_ct windowing(image_array, 250, 0)# 直方图均衡化img_clahe clahe_equalized(img_ct)# 肿瘤掩模图处理livertumor_path frG:/dataPack/基于深度学习的肝脏肿瘤图像分割/3dircadb1/3dircadb1.{num}/MASKS_DICOMtumor_paths [os.path.join(livertumor_path, i) for i in os.listdir(livertumor_path) if livertumor in i]# 重新排序tumor_paths.sort()# 提取所有肿瘤数据j 0for tumor_path in tumor_paths:print(正在处理第%d个肿瘤 % j)tumor_slices [pydicom.dcmread(os.path.join(tumor_path, file_name)) for file_name inos.listdir(tumor_path)]# 重新对肿瘤片段图排序tumor_slices.sort(keylambda x: x.InstanceNumber)# 提取像素值tumor_array np.array([i.pixel_array for i in tumor_slices])# 没有肿瘤的掩模图全为黑色对应像素全为0index [i.sum() 0 for i in tumor_array] # 提取肿瘤部分编号img_tumor tumor_array[index]# 对增强后的CT图提取肿瘤img_patient img_clahe[index]# 保存所有肿瘤数据for i in range(len(img_patient)):plt.imsave(os.path.join(patient_save_path, f{num}_{j}_{i}.jpg), img_patient[i], cmapgray) # 保存CT图plt.imsave(os.path.join(tumor_save_path, f{num}_{j}_{i}.jpg), img_tumor[i], cmapgray) # 保存肿瘤掩模图j 1return img_patient, img_tumor 处理后保存的CT增强图像与肿瘤掩模图 数据集加载
定义Dataset数据加载器对样本中每个图片进行进一步处理转成np数组并转换维度方便UNet网络训练通过Dataloader中定义batch_size设置每批数据大小为2从计算角度来提高训练效率
transform transforms.Compose([transforms.Resize((512, 512)),transforms.ToTensor()
]) 首先读取本地文件设置训练集与测试集文件路径通过torch.squeeze(anno_tensor).type(torch.long)将肿瘤图转化为单通道数组
并对肿瘤图进行二值化处理
# 读取之前保存的处理后的病人CT图片与肿瘤图片
train_img_patient, train_img_tumor processImage(1, 5)
test_img_patient, test_img_tumor processImage(5, 7)
patient_images glob.glob(rE:\\datasets\liver\tmp\patient\*.jpg)
tumor_images glob.glob(rE:\\datasets\liver\tmp\tumor\*.jpg)
train_images [p for p in patient_images if 1_ in p]
train_labels [p for p in tumor_images if 1_ in p]
test_images [p for p in patient_images if 2_ in p]
test_labels [p for p in tumor_images if 2_ in p]
train_images np.array(train_images)
train_labels np.array(train_labels)
test_images np.array(test_images)
test_labels np.array(test_labels)
# img Image.open(train_images[1])
# plt.imshow(img)
# plt.show()class Portrait_dataset(data.Dataset):def __init__(self, img_paths, anno_paths):self.imgs img_pathsself.annos anno_pathsdef __getitem__(self, index):img self.imgs[index]anno self.annos[index]pil_img Image.open(img)img_tensor transform(pil_img)pil_anno Image.open(anno)anno_tensor transform(pil_anno)# 由于蒙版图都是黑白图会产生channel为1的维度。经过转换后256x256x1这个1并不是我们需要的。anno_tensor torch.squeeze(anno_tensor).type(torch.long)anno_tensor[anno_tensor 0] 1 # 语义分割。二分类。return img_tensor, anno_tensordef __len__(self):return len(self.imgs)BATCH_SIZE 2
train_set Portrait_dataset(train_images, train_labels)
test_set Portrait_dataset(test_images, test_labels)
train_dataloader data.DataLoader(train_set, batch_sizeBATCH_SIZE, shuffleTrue)
test_dataloader data.DataLoader(test_set, batch_sizeBATCH_SIZE)
img_batch, anno_batch next(iter(train_dataloader))
通过DataSet读取数据集在通过DataLoader设置批处理图片数量2提高计算效率
随机选取病人CT图和肿瘤图展示 五. UNet神经网络模型搭建
Unet网络结构是对称的蓝/白色框表示 feature map蓝色箭头表示 3x3 卷积用于特征提取灰色箭头表示 skip-connection用于特征融合红色箭头表示池化 pooling用于降低维度绿色箭头表示上采样 upsample用于恢复维度青色箭头表示 1x1 卷积用于输出结果。 class downSample(nn.Module):def __init__(self, in_channels, out_channels):super(downSample, self).__init__()# 两层*卷积激活self.conv_relu nn.Sequential(# padding1希望图像经过卷积之后大小不变nn.Conv2d(in_channels, out_channels, kernel_size3, padding1),nn.ReLU(inplaceTrue),nn.Conv2d(out_channels, out_channels, kernel_size3, padding1),nn.ReLU(inplaceTrue))# 下采样池化self.pool nn.MaxPool2d(kernel_size2)def forward(self, x, is_poolTrue):if is_pool:x self.pool(x)print(downSample forward x.shape,x.shape)x self.conv_relu(x)print(downSample forward after conv_relu(x) x.shape,x.shape)return x# 上采样模型。卷积、卷积、上采样反卷积实现上采样
class upSample(nn.Module):def __init__(self, channels):# 两层*卷积层激活层super(upSample, self).__init__()self.conv_relu nn.Sequential(nn.Conv2d(2 * channels, channels, kernel_size3, padding1),nn.ReLU(inplaceTrue),nn.Conv2d(channels, channels, kernel_size3, padding1),nn.ReLU(inplaceTrue))# 上采样激活层ConvTransposed将输出层的channel变成原来的一半self.upConv_relu nn.Sequential(nn.ConvTranspose2d(channels, channels // 2,kernel_size3, stride2,padding1, output_padding1),nn.ReLU(inplaceTrue))def forward(self, x):print(upSample - forward x.shape,x.shape)x self.conv_relu(x)x self.upConv_relu(x)return x# 创建Unet。要初始化上、下采样层还有其他的一些层
class Unet(nn.Module):def __init__(self):super(Unet, self).__init__()self.down1 downSample(3, 64)self.down2 downSample(64, 128)self.down3 downSample(128, 256)self.down4 downSample(256, 512)self.down5 downSample(512, 1024)self.up nn.Sequential(nn.ConvTranspose2d(1024, 512,kernel_size3,stride2,padding1,output_padding1),nn.ReLU(inplaceTrue))self.up1 upSample(512)self.up2 upSample(256)self.up3 upSample(128)self.conv_2 downSample(128, 64) # 最后两层卷积self.last nn.Conv2d(64, 2, kernel_size1) # 输出层为2分类def forward(self, x):x1 self.down1(x, is_poolFalse)x2 self.down2(x1)x3 self.down3(x2)x4 self.down4(x3) # ([512, 64, 64])print(x4.shape,x4.shape) # x4.shape torch.Size([512, 64, 64])x5 self.down5(x4)print(x5.shape,x5.shape) # x5.shape torch.Size([1024, 32, 32])x6 self.up(x5)print(x6.shape,x6.shape) # x6.shape torch.Size([512, 64, 64])# 将下采用过程x4的输出与上采样过程x5的输出做一个合并x6 torch.cat([x4, x6], dim0) # dim0print(x6.shape,x6.shape) # x6.shape torch.Size([512, 128, 64])x7 self.up1(x6)x7 torch.cat([x3, x7], dim0)x8 self.up2(x7)x8 torch.cat([x2, x8], dim0)x9 self.up3(x8)x9 torch.cat([x1, x9], dim0)x10 self.conv_2(x9, is_poolFalse)result self.last(x10)return result
神经网络中图像shape变化图 单张图片预测图