使用VisualDL可视化基于PaddleSeg的眼底血管分割
VisualDL 是一个面向深度学习任务设计的可视化工具。VisualDL 利用了丰富的图表来展示数据,用户可以更直观、清晰地查看数据的特征与变化趋势,有助于分析数据、及时发现错误,进而改进神经网络模型的设计。
目前,VisualDL 支持 scalar, image, audio, graph, histogram, pr curve, high dimensional 七个组件,项目正处于高速迭代中,敬请期待新组件的加入。
本次项目使用scalar,image和model进行可视化分析。
github首页:https://github.com/PaddlePaddle/VisualDL
官网:https://www.paddlepaddle.org.cn/paddle/visualdl
aistudio项目:https://aistudio.baidu.com/aistudio/projectdetail/502834
https://aistudio.baidu.com/aistudio/projectdetail/622772
aistudio论坛:https://ai.baidu.com/forum/topic/show/960053?pageNo=2
欢迎大家在GitHub上点赞~
一、项目背景
研究表明,各类眼科疾病以及心脑血管疾病会对视网膜血管造成形变、出血等不同程度的影响。随着生活水平的提高,这类疾病的发病率呈现逐年增长的趋势。临床上,医疗人员能够从检眼镜采集的彩色眼底图像中提取视网膜血管,然后通过对血管形态状况的分析达到诊断这类疾病的目的。
但是,由于受眼底图像采集技术的限制,图像中往往存在大量噪声,再加之视网膜血管自身结构复杂多变,使得视网膜血管的分割变得困难重重。
传统方法中依靠人工手动分割视网膜血管,不仅工作量巨大极为耗时,而且受主观因素影响严重。
因此,利用计算机技术,找到一种能够快速、准确分割视网膜血管的算法,实现对眼底图像血管特征的实时提取,对辅助医疗人员诊断眼科疾病、心脑血管疾病等具有重要作用。
二、数据集介绍
本项目使用的数据集照片来自荷兰的糖尿病视网膜病变筛查项目。筛查人群包括400名年龄在25-90岁之间的糖尿病患者。但只有40张照片被选取,其中33张没有显示任何糖尿病视网膜病变的迹象,7张显示轻度早期糖尿病视网膜病变的迹象。
AI Studio上已经有DRIVE糖尿病人眼底血管分割数据集了,但是该数据集的数据量非常少,只有20张训练集。
因此,我在处理数据时做了一些处理来增加我的训练集数据量。
数据集图片格式转换
原数据集里的眼底图像:
原数据集手工分好的的血管图像:
仔细看一下图片格式:
- 眼底图像格式是.tif
- 手工标注的血管图像格式是.gif
这里我做了图片格式的转换:
- 把眼底图像格式转换为.jpg
- 把手工标注的血管图像格式转换为.png
这里做格式转换的目的是我想把数据集放到PaddleX里试着运行一下,但它的图片格式只支持png, jpg, jpeg, bmp格式,因此,我这里做了一个格式转换。
血管标签图像二值化
如果直接将格式转换后的格式送入模型,会发现最多有256个标签,这是因为PaddleSeg采用单通道的标注图片,每一种像素值代表一种类别,像素标注类别需要从0开始递增,例如0,1,2,3表示有4种类别,所以标注类别最多为256类。
但其实我们只需要找到血管的位置,因此血管就作为一个类,其背景作为另一个类别,这样总共有2个类别。下面来看一下如何使用opencv做图像二值化处理。
先来看看如何使用opencv读取图片,下面是未处理的图片0.png,位于work目录下:
In [2]:
# 使用opencv读取图像
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("work/0.png") # 读取的图片路径
plt.imshow(img)
plt.show()
In [4]:
# 使用opencv读取图像
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("work/0.png") # 读取的图片路径
# 转换为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_gray)
plt.show()
In [5]:
# 使用opencv读取图像
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("work/0.png") # 读取的图片路径
# 转换为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度极差的一半作为阈值
difference = (img_gray.max() - img_gray.min()) // 2
# 将图像二值化
_, img_binary = cv2.threshold(img_gray, difference, 1, cv2.THRESH_BINARY)
print("阈值:", _)
plt.imshow(img_binary)
plt.show()
阈值: 127.0
将上面的代码整理一下,可以整理出如下代码:
import cv2
import matplotlib.pyplot as plt
#循环灰度图片并保存
def grayImg():
for x in range(200):
#读取图片
img = cv2.imread("FundusVessels/Annotations/{}.png".format(str(x)))
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
difference = (img_gray.max() - img_gray.min()) // 2
_, img_binary = cv2.threshold(img_gray, difference, 1, cv2.THRESH_BINARY)
# print("阈值:", _)
#保存灰度后的新图片
cv2.imwrite("FundusVessels/{}.png".format(str(x)), img_binary)
plt.imshow(img_binary)
plt.show()
grayImg()
以上代码可以将像素值在0-255的图像转换成0-1二值图像。最后我已经将整理好的数据集上传至AI Studio,同时也加载到该项目上了: https://aistudio.baidu.com/aistudio/datasetdetail/56726
我们也可以把数据集导入PaddleX可视化地看一下:
生成图像列表
PaddleSeg采用通用的文件列表方式组织训练集、验证集和测试集。在训练、评估、可视化过程前必须准备好相应的文件列表。
文件列表组织形式如下
原始图片路径 [SEP] 标注图片路径
其中[SEP]是文件路径分割符,可以在DATASET.SEPARATOR配置项中修改, 默认为空格。文件列表的路径以数据集根目录作为相对路径起始点,DATASET.DATA_DIR即为数据集根目录。
如下图所示,左边为原图的图片路径,右边为图片对应的标注路径:
In [15]:
# 解压数据集
!unzip data/data56918/FundusVessels.zip
In [16]:
# 生成图像列表
import os
path_origin = 'FundusVessels/JPEGImages/'
path_seg = 'FundusVessels/Annotations/'
pic_dir = os.listdir(path_origin)
f_train = open('train_list.txt', 'w')
f_val = open('val_list.txt', 'w')
for i in range(len(pic_dir)):
if i % 30 != 0:
f_train.write(path_origin + pic_dir[i] + ' ' + path_seg + pic_dir[i].split('.')[0] + '.png' + '\n')
else:
f_val.write(path_origin + pic_dir[i] + ' ' + path_seg + pic_dir[i].split('.')[0] + '.png' + '\n')
f_train.close()
f_val.close()
二、PaddleSeg的安装
PaddleSeg是基于PaddlePaddle生态下的语义分割库,可结合丰富的预训练模型更便捷高效地进行语义分割。
本项目已经挂载了PaddleSeg压缩包,解压即可使用。
注: 在AI studio中运行shell命令需要在最开始添加!
In [ ]:
# 解压从PaddleSeg Github仓库下载好的压缩包
!unzip -o work/PaddleSeg.zip
# 运行脚本需在PaddleSeg目录下
%cd PaddleSeg
# 安装所需依赖项
!pip install -r requirements.txt
三、配置文件进行训练
这里我们需要使用两个文件:
- 训练文件:PaddleSeg/pdseg/train.py
- 训练的配置文件:PaddleSeg/configs/unet_optic.yaml
这里使用U-Net,大家可以尝试使用其他网络进行配置。
.yaml文件的配置
下面是我配置的.yaml文件,
# 数据集配置
DATASET:
DATA_DIR: ""
NUM_CLASSES: 2
TEST_FILE_LIST: "train_list.txt"
TRAIN_FILE_LIST: "train_list.txt"
VAL_FILE_LIST: "val_list.txt"
VIS_FILE_LIST: "train_list.txt"
# 预训练模型配置
MODEL:
MODEL_NAME: "unet"
DEFAULT_NORM_TYPE: "bn"
# 其他配置
TRAIN_CROP_SIZE: (565, 584)
EVAL_CROP_SIZE: (565, 584)
AUG:
AUG_METHOD: "unpadding"
FIX_RESIZE_SIZE: (565, 584)
BATCH_SIZE: 4
TRAIN:
# PRETRAINED_MODEL_DIR: "./pretrained_model/unet_bn_coco/"
MODEL_SAVE_DIR: "./saved_model/unet_optic/"
SNAPSHOT_EPOCH: 2
TEST:
TEST_MODEL: "./saved_model/unet_optic/final"
SOLVER:
NUM_EPOCHS: 10
LR: 0.001
LR_POLICY: "poly"
OPTIMIZER: "adam"
开始训练
训练命令的格式参考:
!python PaddleSeg/pdseg/train.py --cfg PaddleSeg/configs/unet_optic.yaml --use_vdl --vdl_log_dir vdl_log_dir --do_eval
In [6]:
!python PaddleSeg/pdseg/train.py --cfg PaddleSeg/configs/unet_optic.yaml --use_vdl --vdl_log_dir vdl_log_dir --do_eval
使用VisualDL进行可视化
在可视化模块中配置logdir路径为./vdl_log_dir 可对训练过程进行监控 模型训练时生成日志和模型文件,按照下面的步骤就可以在aistudio上使用VisualDL进行可视化。
scalar功能
scalar功能
上图中的横坐标代表loss纵坐标代表step.通过scala可以很明显的看到loss是否在下降与下降的速度,这样很方便我们做相应参数的调整。
鼠标放在图像上时会自动显示图像上的相关信息,上图中最右侧提供了很多选项,可以按照自己的需求进行选择。
image功能
上图显示了模型训练中所用到的数据。
graph功能
graph功能展示了所用模型的网络结构,使用鼠标点击所展示的网络结构可以在左侧显示所点部分的具体参数信息。
VisualDL相关资料
github首页:https://github.com/PaddlePaddle/VisualDL
官网:https://www.paddlepaddle.org.cn/paddle/visualdl
aistudio项目:https://aistudio.baidu.com/aistudio/projectdetail/502834
https://aistudio.baidu.com/aistudio/projectdetail/622772
aistudio论坛:https://ai.baidu.com/forum/topic/show/960053?pageNo=2
欢迎大家在GitHub上点赞~