我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 2056|回复: 10

[技术文章] 深度网络图像分割通俗指南

[复制链接]
  • TA的每日心情

    昨天 18:16
  • 签到天数: 99 天

    [LV.6]常住居民II

    3万

    主题

    8253

    回帖

    8万

    积分

    三级逆天

    积分
    81480

    终身成就奖特殊贡献奖原创先锋奖金点子奖优秀斑竹奖宣传大使奖

    发表于 2017-11-8 13:29:47 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×
    介绍如何使用当前最先进的深度学习方法来区分图像中的前景与背景、家具与非家具,并从一张照片中提取出椅子。

                                   
    登录/注册后可看大图

    给定一张包含家具的照片,你可以让程序自动将家具与背景分开吗?
    在这篇文章中,我将介绍如何使用当前最先进的深度学习来尝试解决这个问题。我不是机器学习的专家,所以我希望这个帖子对于其他希望使用这个强大新工具的非专家们有一定的帮助作用。
    这个问题称为分割。也就是说,从这张图开始:

                                   
    登录/注册后可看大图

    到这张图:

                                   
    登录/注册后可看大图

    我们可以将这个遮罩应用到源图像上,获得没有背景的椅子。我们将使用一些工具来简化这个工作:
    keras - 一个非常棒的用于创建神经网络的库。 Keras是像Tensorflow这样的较低级别库的前端,它能为用户处理构建神经网络过程中存在的大量繁琐的细节。。
    U-Net - 用于图像分割的神经网络架构。 U-Net最初被设计用于生物医学图像分割(例如,在CT扫描中识别肺结节),但它也可用于分割常规2D图像。在下文将看到,即使没有大数据集,U-Net的强大功能也能让你大吃一惊。
    Brine - 一个数据集管理器,可以利用该管理器轻松地共享和管理图像数据集。构建模型最令人讨厌的部分就是获取和选择用于训练模型的数据集。我创建了brine来轻松共享数据集,使之能应用在PyTorch/Keras模型上。我们将使用它来下载数据集并将其与Keras进行交互。
    一个Github代码库 - Carvana图像遮罩挑战赛是Kaggle的一项赛事,它提出了类似的问题:将汽车从背景中扣出来。人们经常在Kaggle比赛中分享他们的解决方案,而在这个代码库中,有人分享了一个使用Keras和U-Net的解决方案。我们的目标是利用这个解决方案来解决我们当前这个家具分割问题。
    一个数据集 - 这是一个朋友提供的数据集。请注意,它非常的小,只包含了97张椅子和相应的遮罩。一般来说我不会指望通过这么少的数据来做很多的工作(Carvana挑战赛中提供了数千个样本),但是让我们来看看最终到底可以做到何种程度吧。
    代码
    这里有一个jupyter笔记,其中包含了建立模型的所有代码。我将重点介绍其中最重要的部分,并解释它的原理。
    第一步是安装数据集。由于它托管在Brine上,所以可以用一个简单的命令来实现:brine install rohan/chairs-with-masks。
    下一步是加载数据集。可以通过Brine的load_dataset函数来执行此操作:chairs = brine.load_dataset('rohan/chairs-with-masks')。该数据集包含了97个样本,每个样本是图像及其遮罩。遮罩是一个只有两种颜色的图像,蓝色代表背景,红色代表前景。
    数据集加载了,现在来加载U-Net网络。把“Kaggle-Carvana-Image-Masking-Challenge”代码库中的model目录复制下来。导入这个网络,执行model = unet.get_unet_256() 。感谢petrosgk的工作,只需调用这一个函数即可返回一个Keras内置的U-Net网络。 Keras提供了model.summary()方法来查看网络的结构,虽然从中可以看到大量的信息,但最重要的是第一个和最后一个,它告诉了我们网络期望的输入和输出的形状。
    我们可以看到输入的形状是(None, 256, 256, 3),输出的形状是(None, 256, 256, 1)。元组的第一个元素是批量的大小,所以我们现在可以忽略它。这告诉我们,网络期望的输入是一批256x256的三通道图像,并将输出一批256x256个单通道遮罩。我们的遮罩也需要匹配这个形状。
    下一步是准备样本,使之与网络一起使用。我们将为训练数据定义一个处理函数,在样本传给网络之前需应用于每个样本。
    def fix_mask(mask): mask[mask < 100] = 0.0mask[mask >= 100] = 255.0def train_process(sample): img, mask= sample img= img[:,:,: 3] mask= mask[:, :, : 3] mask= cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) fix_mask(mask) img= cv2.resize(img, SIZE) mask= cv2.resize(mask, SIZE) img= randomHueSaturationValue(img, hue_shift_limit=(-50,50), sat_shift_limit=(0,0), val_shift_limit=(-15,15)) img, mask= randomShiftScaleRotate(img, mask, shift_limit=(-0.062,0.062), scale_limit=(-0.1,0.1), rotate_limit=(-20,20)) img, mask= randomHorizontalFlip(img, mask) fix_mask(mask) img= img/ 255. mask= mask/ 255. mask= np.expand_dims(mask, axis=2)return (img, mask)
    这里做了很多事情,我会一步一步进行解释。样本作为一个元组被传递进去,所以首先要进行解包。接下来的两行使用numpy切片来确保图像只有3个通道,如果有第四个alpha通道,则忽略。然后,使用cv2(OpenCV的python绑定)将遮罩转换为灰度图,这样,我们现在就有了一个单通道遮罩,这是网络所期望的。这里没有为两种颜色使用两个随机的灰度数字,而是强制使用fix_mask函数将掩码设置为0和255以表示背景和前景。然后,我们将图像和掩码的大小调整为256x256,以匹配网络指定的大小。
    由于数据集较小,因此我们将使用数据扩充。数据扩充是指在训练期间在保留原始信息的基础上随机修改图像,人为地生成更多的数据。例如,旋转5度的椅子仍然是椅子,所以网络应该能够正确地识别出来。在代码中,我们使用petrosgk的Carvana示例中的3个函数来随机改变图像的色相、饱和度和值,并随机旋转和翻转图像。如果旋转或翻转了图像,则必须对遮罩执行相同的操作,以使遮罩与原始图像保持一致。
    最后,我们通过将所有像素值除以255来对数据进行归一化操作,这样,所有的值都在0和1之间了。如果在此时打印image.shape,结果是256x256x3,这正是网络所需要的。尽管mask.shape是256x256,但网络是256x256x1,所以我们使用np.expand_dims来让遮罩匹配这个形状。最后,返回新的图像和遮罩。
    在开始训练网络之前,还需要用一些样本进行验证。验证集不能用于训练,只能用于检查模型的性能。我们可以使用Brine的create_folds来创建:
    validation_fold, train_fold = chairs.create_folds((20,))
    我们将样本集中的20个图像作为验证集,剩下的77个图像作为训练集。
    我们还定义了用于样本验证的处理函数,这与用于训练的处理函数非常相似,除了在验证时不使用数据扩充之外。
    最后,Brine返回一个可用于训练和校验集的图片生成器:
    train_generator= train_fold.to_keras( 'image', 'mask', batch_size=BATCH_SIZE,shuffle=True,processing_function=train_process)validation_generator= validation_fold.to_keras( 'image', 'mask', batch_size=BATCH_SIZE,shuffle=False,processing_function=validation_process)
    这些生成器将返回样品的批处理,以及之前定义的处理函数。它们可以被直接传给Keras的fit_generator方法来训练模型。
    现在,准备开始训练模型了:
    callbacks= [EarlyStopping( monitor='val_loss',patience=8,verbose=1,min_delta=1e-4),ReduceLROnPlateau( monitor='val_loss',factor=0.1,patience=4,verbose=1,epsilon=1e-4),ModelCheckpoint( monitor='val_loss',filepath='weights/best_weights.hdf5',save_best_only=True,save_weights_only=True)]
    这些回调会改变Keras的训练过程。 EarlyStopping将在验证损失的改进停止后停止训练,ReduceLROnPlateau将降低学习率,ModelCheckpoint将对在验证集上表现最佳的模型版本进行保存。
    最后,可以开始训练了:
    epochs=100model.fit_generator( generator=train_generator,steps_per_epoch=train_generator.steps_per_epoch(),epochs=epochs,callbacks=callbacks,validation_data=validation_generator,validation_steps=validation_generator.steps_per_epoch())
    Keras开始训练模型了,它将在数据集上运行多次(由于数据增加和混洗,每次运行的结果会略有不同),并输出训练和验证集的损失和DICE分数。在某些时候,运行会停止,可能是因为EarlyStopping回调,或是因为达到了100次迭代。
    好了,就这些!我们训练了一个U-Net网络,并尝试在图像中把椅子分割出来。让我们来看看它的实际表现如何吧。
    生成预测
    要产生一些预测,首先使用model.load_weights('weights/best_weights.hdf5')来加载最佳模型的权重,然后在验证集中的某些图像上使用模型的predict方法:
    def predict_one(): image_batch, mask_batch= next(validation_generator) predicted_mask_batch= model.predict(image_batch) image= image_batch[ 0] predicted_mask= predicted_mask_batch[ 0].reshape(SIZE) plt.imshow(image) plt.imshow(predicted_mask, alpha=0.6)
    以下是一些样本的结果:

                                   
    登录/注册后可看大图

    在原始图像上覆盖了网络预测出来的遮罩。颜色越黄,则说明网络对该像素的预测具有更高的置信度
    虽然这对于生产系统来说还不够好,但网络已经学到了有关前景与背景、椅子与非椅子的一些内容。我个人觉得这个网络在没有进行预先训练,并且只有77张图片的情况下表现得已经非常不错了。如果有更大的数据集,网络的准确性可能会大大提高,或许就能用于生产系统了。
    回复

    使用道具 举报

  • TA的每日心情

    前天 08:00
  • 签到天数: 161 天

    [LV.7]常住居民III

    249

    主题

    3647

    回帖

    1万

    积分

    三级逆天

    积分
    10407

    终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2017-11-8 15:08:17 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    17

    主题

    122

    回帖

    177

    积分

    1元学习PADS(5期)

    积分
    177

    终身成就奖

    QQ
    发表于 2017-11-8 22:47:32 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-5-29 20:33
  • 签到天数: 1 天

    [LV.1]初来乍到

    112

    主题

    6493

    回帖

    7867

    积分

    二级逆天

    积分
    7867

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2017-11-8 23:07:21 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-10-7 21:17
  • 签到天数: 103 天

    [LV.6]常住居民II

    92

    主题

    1万

    回帖

    7万

    积分

    三级逆天

    积分
    73181

    终身成就奖特殊贡献奖原创先锋奖社区居民忠实会员社区劳模最爱沙发社区明星原创达人优秀斑竹奖宣传大使奖

    QQ
    发表于 2017-11-9 08:36:10 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    4

    主题

    234

    回帖

    451

    积分

    二级逆天

    积分
    451

    终身成就奖

    QQ
    发表于 2017-11-9 08:38:18 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    前天 08:31
  • 签到天数: 145 天

    [LV.7]常住居民III

    7

    主题

    2495

    回帖

    2313

    积分

    二级逆天

    积分
    2313

    终身成就奖优秀斑竹奖特殊贡献奖

    QQ
    发表于 2017-11-9 08:45:29 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    6

    主题

    1570

    回帖

    2780

    积分

    二级逆天

    积分
    2780

    终身成就奖原创先锋奖

    QQ
    发表于 2017-11-9 08:49:12 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    887

    回帖

    450

    积分

    二级逆天

    积分
    450

    终身成就奖社区居民优秀斑竹奖

    QQ
    发表于 2017-11-29 10:26:22 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    8

    主题

    2158

    回帖

    0

    积分

    二级逆天

    积分
    0

    社区居民终身成就奖

    QQ
    发表于 2019-5-2 09:22:21 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    每日签到,有金币领取。


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    ( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

    平平安安
    TOP
    快速回复 返回顶部 返回列表