项目工程文件结构如下:
参考了Retina_Unet项目,决定自己用代码来实现一遍,数据增强不是像Retina_Unet那样随机裁剪,而是将20个训练数据集按顺序裁剪,每张裁剪成48x48大小的144个patch,20张一共裁剪出2880个patch。
Unet模型:模型输入的张量形状为(Npatch,1,48,48),输出为(Npatch,2304,2)。Npatch表示训练集的样本数,本例中训练时为2880,预测时为144。
训练:把原作者代码中的SGD改为Adam,效果有提升。
预测:也需要先把待预测图像分割成48×48的小图,输入模型,然后把结果整理还原为完整图像,再和专家标注结果进行对比。代码中以测试集第一张图片为例,可自行修改为其他眼底图片路径。
util.py
import numpy as np
import cv2
import os
from PIL import Image
def read_image_and_name(path):
imgdir = os.listdir(path)
imglst = []
imgs = []
for v in imgdir:
imglst.append(path + v)
imgs.append(cv2.imread(path + v))
print(imglst)
print('original images shape: ' + str(np.array(imgs).shape))
return imglst,imgs
def read_label_and_name(path):
labeldir = os.listdir(path)
labellst = []
labels = []
for v in labeldir:
labellst.append(path + v)
labels.append(np.asarray(Image.open(path + v)))
print(labellst)
print('original labels shape: ' + str(np.array(labels).shape))
return labellst,labels
def resize(imgs,resize_height, resize_width):
img_resize = []
for file in imgs:
img_resize.append(cv2.resize(file,(resize_height,resize_width)))
return img_resize
#将N张576x576的图片裁剪成48x48
def crop(image,dx):
list = []
for i in range(image.shape[0]):
for x in range(image.shape[1] // dx):
for y in range(image.shape[2] // dx):
list.append(image[ i, y*dx : (y+1)*dx, x*dx : (x+1)*dx]) #这里的list一共append了20x12x12=2880次所以返回的shape是(2880,48,48)
return np.array(list)
# 网络预测输出转换成图像子块
# 网络预测输出 size=[Npatches, patch_height*patch_width, 2]
def pred_to_imgs(pred, patch_height, patch_width, mode="original"):
assert (len(pred.shape)==3) #3D array: (Npatches,height*width,2)
assert (pred.shape[2]==2 ) #check the classes are 2 # 确认是否为二分类
pred_images = np.empty((pred.shape[0],pred.shape[1])) #(Npatches,height*width)
if mode=="original": # 网络概率输出
for i in range(pred.shape[0]):
for pix in range(pred.shape[1]