赞
踩
unet 网络结构是比较常用的图像分割网络结构。这里使用了unet网络结构 对眼底血管进行了分割。整个代码参考了。retina-unet。整个网络准确率还是不错的。
整个眼底血管的图片如下。、
上面展示了一个眼底血管的图像以及它的分割例子。我们可以发现整个图像的血管完整给分割出来了。
这里我也不详细介绍unet网络的整体结构了。相信既然看这个的人基本都是有一定基础的。这里unet网络使用了keras 基于tensorflow 进行编写。
def get_unet(n_ch,patch_height,patch_width): inputs = Input(shape=(n_ch,patch_height,patch_width)) conv1 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(inputs) conv1 = Dropout(0.2)(conv1) conv1 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv1) pool1 = MaxPooling2D((2, 2))(conv1) conv2 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(pool1) conv2 = Dropout(0.2)(conv2) conv2 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv2) pool2 = MaxPooling2D((2, 2))(conv2) conv3 = Conv2D(128, (3, 3), activation='relu', padding='same',data_format='channels_first')(pool2) conv3 = Dropout(0.2)(conv3) conv3 = Conv2D(128, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv3) up1 = UpSampling2D(size=(2, 2))(conv3) up1 = concatenate([conv2,up1],axis=1) conv4 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(up1) conv4 = Dropout(0.2)(conv4) conv4 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv4) # up2 = UpSampling2D(size=(2, 2))(conv4) up2 = concatenate([conv1,up2], axis=1) conv5 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(up2) conv5 = Dropout(0.2)(conv5) conv5 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv5) conv6 = Conv2D(2, (1, 1), activation='relu',padding='same',data_format='channels_first')(conv5) conv6 = core.Reshape((2,patch_height*patch_width))(conv6) conv6 = core.Permute((2,1))(conv6) conv7 = core.Activation('softmax')(conv6) model = Model(inputs=inputs, outputs=conv7) model.compile(optimizer='sgd', loss='categorical_crossentropy',metrics=['accuracy']) return model
这是整个unet网络的设计结构。这里只进行了两次下采样操作。为什么只进行了两次下采样。图片那么大可以吗?这些问题我后面再说。
既然网络已经设计好了。下面就要开始跑数据了。在打开DRIVE 训练集时,我们发现整个图片量太小了。所以要进行扩充操作。这里原本的图片大小为
565
×
584
565 \times584
565×584 .所以这里进行了裁剪运算随机在中心图片上采取了
48
×
48
48\times48
48×48大小的图片进行卷积操作。这也就是为什么上面的unet 网络设计为两次下采样。因为这样完全就可以了。另外图片还进行了
1.Gray-scale conversion
2.Standardization
3.Contrast-limited adaptive histogram equalization (CLAHE)
4.Gamma adjustment’
这样的四步操作。代码如下
def get_data_training(DRIVE_train_imgs_original, DRIVE_train_groudTruth, patch_height, patch_width, N_subimgs, inside_FOV): train_imgs_original = load_hdf5(DRIVE_train_imgs_original) train_masks = load_hdf5(DRIVE_train_groudTruth) #masks always the same # visualize(group_images(train_imgs_original[0:20,:,:,:],5),'imgs_train')#.show() #check original imgs train train_imgs = my_PreProc(train_imgs_original) train_masks = train_masks/255. train_imgs = train_imgs[:,:,9:574,:] #cut bottom and top so now it is 565*565 train_masks = train_masks[:,:,9:574,:] #cut bottom and top so now it is 565*565 data_consistency_check(train_imgs,train_masks) #check masks are within 0-1 assert(np.min(train_masks)==0 and np.max(train_masks)==1) print("\ntrain images/masks shape:") print(train_imgs.shape) print("train images range (min-max): " +str(np.min(train_imgs)) +' - '+str(np.max(train_imgs))) print("train masks are within 0-1\n") #extract the TRAINING patches from the full images patches_imgs_train, patches_masks_train = extract_random(train_imgs,train_masks,patch_height,patch_width,N_subimgs,inside_FOV) data_consistency_check(patches_imgs_train, patches_masks_train) print("\ntrain PATCHES images/masks shape:") print(patches_imgs_train.shape) print("train PATCHES images range (min-max): " +str(np.min(patches_imgs_train)) +' - '+str(np.max(patches_imgs_train))) return patches_imgs_train, patches_masks_train#, patches_imgs_test, patches_masks_test
这是获得随机大小的代码。
def histo_equalized(imgs): assert (len(imgs.shape)==4) #4D arrays assert (imgs.shape[1]==1) #check the channel is 1 imgs_equalized = np.empty(imgs.shape) for i in range(imgs.shape[0]): imgs_equalized[i,0] = cv2.equalizeHist(np.array(imgs[i,0], dtype = np.uint8)) return imgs_equalized # CLAHE (Contrast Limited Adaptive Histogram Equalization) #adaptive histogram equalization is used. In this, image is divided into small blocks called "tiles" (tileSize is 8x8 by default in OpenCV). Then each of these blocks are histogram equalized as usual. So in a small area, histogram would confine to a small region (unless there is noise). If noise is there, it will be amplified. To avoid this, contrast limiting is applied. If any histogram bin is above the specified contrast limit (by default 40 in OpenCV), those pixels are clipped and distributed uniformly to other bins before applying histogram equalization. After equalization, to remove artifacts in tile borders, bilinear interpolation is applied def clahe_equalized(imgs): assert (len(imgs.shape)==4) #4D arrays assert (imgs.shape[1]==1) #check the channel is 1 #create a CLAHE object (Arguments are optional). clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) imgs_equalized = np.empty(imgs.shape) for i in range(imgs.shape[0]): imgs_equalized[i,0] = clahe.apply(np.array(imgs[i,0], dtype = np.uint8)) return imgs_equalized # ===== normalize over the dataset def dataset_normalized(imgs): assert (len(imgs.shape)==4) #4D arrays assert (imgs.shape[1]==1) #check the channel is 1 imgs_normalized = np.empty(imgs.shape) imgs_std = np.std(imgs) imgs_mean = np.mean(imgs) imgs_normalized = (imgs-imgs_mean)/imgs_std for i in range(imgs.shape[0]): imgs_normalized[i] = ((imgs_normalized[i] - np.min(imgs_normalized[i])) / (np.max(imgs_normalized[i])-np.min(imgs_normalized[i])))*255 return imgs_normalized def adjust_gamma(imgs, gamma=1.0): assert (len(imgs.shape)==4) #4D arrays assert (imgs.shape[1]==1) #check the channel is 1 # build a lookup table mapping the pixel values [0, 255] to # their adjusted gamma values invGamma = 1.0 / gamma table = np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]).astype("uint8") # apply gamma correction using the lookup table new_imgs = np.empty(imgs.shape) for i in range(imgs.shape[0]): new_imgs[i,0] = cv2.LUT(np.array(imgs[i,0], dtype = np.uint8), table) return new_imgs
这是进行图像预处理的四个步骤。
既然网络结构设计好了以后,现在进行程序运行操作。在经过200轮的迭代以后。可以获得准确率在95%左右。下一本在进行评估操作。要对剩下的测试数据进行操作。
最后整个ROC曲线达到了97.6%。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。