首页 文章 精选 留言 我的

精选列表

搜索[top1],共147篇文章
优秀的个人博客,低调大师

医学图像分割模型U-Net介绍和Kaggle的Top1解决方案源码解析

内容列表 介绍 先决条件 什么是U-NET U-NET结构 KAGGLE数据科学SCIENCE BOWL 2018 挑战赛 介绍 计算机视觉是人工智能的一个领域,训练计算机解释和理解视觉世界。利用来自相机、视频和深度学习模型的数字图像,机器可以准确地识别和分类物体,然后对它们看到的东西做出反应。 在过去几年里,深度学习使得计算机视觉领域迅速发展。在这篇文章中,我想讨论计算机视觉中一个叫做分割的特殊任务。尽管研究人员已经提出了许多方法来解决这个问题,但我将讨论一种特殊的架构,即UNET,它使用一个完全卷积的网络模型来完成这项任务。 我们将利用UNET构建Kaggle SCIENCE BOWL 2018 挑战赛的第一解决方案。 先决条件 这篇文章是假设读者已经熟悉机器学习和卷积网络的基本概念。同时,他/她也有一些使用Python和Keras库的ConvNets的工作知识。 什么是市场细分? 分割的目的是将图像的不同部分分割成可感知的相干部分。细分有两种类型: 语义分割(基于标记类的像素级预测) 实例分割(目标检测和目标识别) 在这篇文章中,我们将主要关注语义分割。 U-NET是什么? U-Net创建于2015年,是一款专为生物医学图像分割而开发的CNN。目前,U-Net已经成为一种非常流行的用于语义分割的端到端编解码器网络。它有一个独特的上下结构,有一个收缩路径和一个扩展路径。 U-NET 结构 U-Net下采样路径由4个block组成,其层数如下: 3x3 CONV (ReLU +批次标准化和Dropout使用) 3x3 CONV (ReLU +批次标准化和Dropout使用) 2x2 最大池化 当我们沿着这些块往下走时,特征图会翻倍,从64开始,然后是128、256和512。 瓶颈层由2个CONV层、BN和Dropout组成 与下采样相似上采样路径由4个块组成,层数如下: 反卷积层 从特征图中拼接出相应的收缩路径 3x3 CONV (ReLU +BN和Dropout) 3x3 CONV (ReLU +BN和Dropout) KAGGLE DATA SCIENCE BOWL 2018 CHALLENGE 这项挑战的主要任务是在图像中检测原子核。通过自动化核检测,你可以帮助更快的解锁治疗。识别细胞核是大多数分析的起点,因为人体30万亿个细胞中的大多数都包含一个充满DNA的细胞核,而DNA是给每个细胞编程的遗传密码。识别细胞核使研究人员能够识别样本中的每个细胞,并通过测量细胞对各种治疗的反应,研究人员可以了解潜在的生物学过程。 样本图像,目标和方法 我们将使用U-Net这个专门为分割任务而设计的CNN自动生成图像遮罩 导入所有必要的包和模块 import osimport sysimport randomimport warningsimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom tqdm import tqdmfrom itertools import chainfrom skimage.io import imread, imshow, imread_collection, concatenate_imagesfrom skimage.transform import resizefrom skimage.morphology import labelfrom keras.models import Model, load_modelfrom keras.layers import Inputfrom keras.layers.core import Dropout, Lambdafrom keras.layers.convolutional import Conv2D, Conv2DTransposefrom keras.layers.pooling import MaxPooling2Dfrom keras.layers.merge import concatenatefrom keras.callbacks import EarlyStopping, ModelCheckpointfrom keras import backend as Kimport tensorflow as tfIMG_WIDTH = 128IMG_HEIGHT = 128IMG_CHANNELS = 3TRAIN_PATH = './U_NET/train/'TEST_PATH = './U_NET/validation/'warnings.filterwarnings('ignore', category=UserWarning, module='skimage')seed = 42random.seed = seednp.random.seed = seed 为训练和测试数据收集我们的文件名 train_ids = next(os.walk(TRAIN_PATH))[1]test_ids = next(os.walk(TEST_PATH))[1] 创建尺寸为128 x 128的图像遮罩(黑色图像) print('Getting and resizing training images ... ')X_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)Y_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool)# Re-sizing our training images to 128 x 128# Note sys.stdout prints info that can be cleared unlike print.# Using TQDM allows us to create progress barssys.stdout.flush()for n, id_ in tqdm(enumerate(train_ids), total=len(train_ids)): path = TRAIN_PATH + id_ img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS] img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True) X_train[n] = img mask = np.zeros((IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool) # Now we take all masks associated with that image and combine them into one single mask for mask_file in next(os.walk(path + '/masks/'))[2]: mask_ = imread(path + '/masks/' + mask_file) mask_ = np.expand_dims(resize(mask_, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True), axis=-1) mask = np.maximum(mask, mask_) # Y_train is now our single mask associated with our image Y_train[n] = mask# Get and resize test imagesX_test = np.zeros((len(test_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)sizes_test = []print('Getting and resizing test images ... ')sys.stdout.flush()# Here we resize our test imagesfor n, id_ in tqdm(enumerate(test_ids), total=len(test_ids)): path = TEST_PATH + id_ img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS] sizes_test.append([img.shape[0], img.shape[1]]) img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True) X_test[n] = imgprint('Done!') 建立U-Net模型 def my_iou_metric(label, pred): metric_value = tf.py_func(iou_metric_batch, [label, pred], tf.float32) return metric_value# Build U-Net model# Note we make our layers varaibles so that we can concatenate or stack# This is required so that we can re-create our U-Net Modelinputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))s = Lambda(lambda x: x / 255) (inputs)c1 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (s)c1 = Dropout(0.1) (c1)c1 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c1)p1 = MaxPooling2D((2, 2)) (c1)c2 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (p1)c2 = Dropout(0.1) (c2)c2 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c2)p2 = MaxPooling2D((2, 2)) (c2)c3 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (p2)c3 = Dropout(0.2) (c3)c3 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c3)p3 = MaxPooling2D((2, 2)) (c3)c4 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (p3)c4 = Dropout(0.2) (c4)c4 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c4)p4 = MaxPooling2D(pool_size=(2, 2)) (c4)c5 = Conv2D(256, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (p4)c5 = Dropout(0.3) (c5)c5 = Conv2D(256, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c5)u6 = Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same') (c5)u6 = concatenate([u6, c4])c6 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (u6)c6 = Dropout(0.2) (c6)c6 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c6)u7 = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same') (c6)u7 = concatenate([u7, c3])c7 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (u7)c7 = Dropout(0.2) (c7)c7 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c7)u8 = Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same') (c7)u8 = concatenate([u8, c2])c8 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (u8)c8 = Dropout(0.1) (c8)c8 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c8)u9 = Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same') (c8)u9 = concatenate([u9, c1], axis=3)c9 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (u9)c9 = Dropout(0.1) (c9)c9 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same') (c9)# Note our output is effectively a mask of 128 x 128outputs = Conv2D(1, (1, 1), activation='sigmoid') (c9)model = Model(inputs=[inputs], outputs=[outputs])model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[my_iou_metric])model.summary() 训练我们的模型 model_path = "./nuclei_finder_unet_1.h5"checkpoint = ModelCheckpoint(model_path, monitor="val_loss", mode="min", save_best_only = True, verbose=1)earlystop = EarlyStopping(monitor = 'val_loss', min_delta = 0, patience = 5, verbose = 1, restore_best_weights = True)# Fit our modelresults = model.fit(X_train, Y_train, validation_split=0.1, batch_size=16, epochs=10, callbacks=[earlystop, checkpoint]) 生成验证数据的预测 # Predict on training and validation data# Note our use of mean_iou metrimodel = load_model('./nuclei_finder_unet_1.h5', custom_objects={'my_iou_metric': my_iou_metric})# the first 90% was used for trainingpreds_train = model.predict(X_train[:int(X_train.shape[0]*0.9)], verbose=1)# the last 10% used as validationpreds_val = model.predict(X_train[int(X_train.shape[0]*0.9):], verbose=1)#preds_test = model.predict(X_test, verbose=1)# Threshold predictionspreds_train_t = (preds_train > 0.5).astype(np.uint8)preds_val_t = (preds_val > 0.5).astype(np.uint8) 在我们的训练数据上显示我们预测的遮罩 ix = random.randint(0, 602)plt.figure(figsize=(20,20))# Our original training imageplt.subplot(131)imshow(X_train[ix])plt.title("Image")# Our original combined mask plt.subplot(132)imshow(np.squeeze(Y_train[ix]))plt.title("Mask")# The mask our U-Net model predictsplt.subplot(133)imshow(np.squeeze(preds_train_t[ix] > 0.5))plt.title("Predictions")plt.show() 最后这里是完整的代码: 数据集:https://www.kaggle.com/c/data-science-bowl-2018 本文代码:https://github.com/bhaveshgoyal27/mediumblogs/blob/master/U-Net.ipynb 作者:Bhavesh Goyal deephub翻译组 本文分享自微信公众号 - DeepHub IMBA(deephub-imba)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册