【项目实践】基于Mask R-CNN的道路物体检测与分割(从数据集制作到视频测试)...
点击上方“3D视觉工坊”,选择“星标”
干货第一时间送达
1、内容概要
Mask R-CNN的框架是对Faster R-CNN的扩展,与BBox识别并行的增加一个分支来预测每一个RoI的分割Mask。Mask分支是应用到每一个RoI上的一个小的FCN,以pix2pix的方式预测分割Mask。
对Mask预测和class预测去耦合。对每个类别独立的预测一个二值Mask,不依赖分类分支的预测结果。
2、部分相关工作说明
2.1、网络结构发展
作为Faster R-CNN的进一步推进,Mask R-CNN网络的发展进程可以如下图所示:
2.2、网络结构原理
为了演示方法的一般性,作者使用多种架构来构建Mask R-CNN。
区分:
(i)用于整个图像上的特征提取的卷积主干架构;
(ii) 网络头(head) 用于对每个RoI单独应用的边界框识别(分类和回归) 和掩码预测。
网络架构:
作者评估了深度为50或101层的ResNet 和ResNeXt网络。Faster R-CNN与ResNets 的实现从第4阶段的最终卷积层中提取了特征,称之为C4。例如, ResNet-50的这个主干由ResNet-50-C4表示。
作者还使用了另一个更有效的称为特征金字塔网络(FPN)主干。FPN使用具有lateral连接的自上而下架构,从单一尺度输入构建一个网络内特征金字塔。具有FPN主干的Faster R-CNN根据其规模从特征金字塔的不同级别提取RoI特征,随后的方法类似于vanilla ResNet。使用ResNet-FPN主干网通过Mask R-CNN进行特征提取,可以在精度和速度方面获得极佳的提升。
算法流程:
a) 将原始图像中的RoI对应到feature map上,坐标位置可能会存在小数,此时直接取整产生一次量化误差;
b) 在feature map的RoI区域上,将其划分成nxn的bins,bins的坐标位置可能会有小数,此时也直接取整,产生第二次量化误差;
c) 最后在每个bin中进行max pooling操作,即可获得固定大小的feature map;
在Mask-RCNN中使用RoIAlign提取固定大小的feature map。其算法流程与RoIPooling一样,只是在a)和b)步骤中,当坐标位置为小数时,不进行量化取整,而是保留小数。在c)步骤里每个bin中均匀取点,点的数值通过双线性插值获得。
实际上,Mask R-CNN中还有一个很重要的改进,就是ROIAlign。
Faster R-CNN存在的问题是:特征图与原始图像是不对准的(mis-alignment),所以会影响检测精度。而Mask R-CNN提出了RoIAlign的方法来取代ROI pooling,RoIAlign可以保留大致的空间位置。
RoIPool是从每个RoI中提取特征。先将浮点数表示的RoI量化到与特征图匹配的粒度,然后将量化后的RoI分块后对每个块进行池化。这些量化使RoI与提取的特征错位。虽然可能不会影响分类,但对于预测像素级精确掩码有很大的负面影响。为了解决这个问题文章提出了一个新的层,称为ROIAlign。文章避免对RoI边界进行量化,即用x/16代替[x/16]。然后对分得的每一个块选取分块中的四个常规位置,并使用双线性插值来计算每一个位置上的精确值,并将结果汇总(池化)。
那么,RoI Pooling和RoI Align的区别在于哪里呢?如何能够精确的反向找到对应像素点边缘?对Pooling的划分不能按照Pooling的边缘,而是要按照像素点缩放后的边缘。
2.4、ResNet-FPN网络
多尺度检测在目标检测中变得越来越重要,对小目标的检测尤其如此。现在主流的目标检测方法很多都用到了多尺度的方法,包括最新的yolo v3。Feature Pyramid Network (FPN)则是一种精心设计的多尺度检测方法,下面就开始简要介绍FPN。
FPN结构中包括自下而上,自上而下和横向连接三个部分,如下图所示。这种结构可以将各个层级的特征进行融合,使其同时具有强语义信息和强空间信息,在特征学习中算是一把利器了。
ResNet-FPN包括3个部分:
自下而上连接;
自上而下连接;
横向连接。
下面分别介绍:
自下而上连接:
从下到上路径。可以明显看出,其实就是简单的特征提取过程,和传统的没有区别。具体就是将ResNet作为骨架网络,根据feature map的大小分为5个stage。stage2,stage3,stage4和stage5各自最后一层输出conv2,conv3,conv4和conv5分别定义为C2,C3,C4,C5,他们相对于原始图片的stride是{4,8,16,32}。需要注意的是,考虑到内存原因,stage1的conv1并没有使用。
自上而下和横向连接:
自上而下是从最高层开始进行上采样,这里的上采样直接使用的是最近邻上采样,而不是使用反卷积操作,一方面简单,另外一方面可以减少训练参数。横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合。具体就是对 C2,C3,C4,C5中的每一层经过一个conv 1x1操作(1x1卷积用于降低通道数),无激活函数操作,输出通道全部设置为相同的256通道,然后和上采样的feature map进行加和操作。在融合之后还会再采用3*3的卷积核对已经融合的特征进行处理,目的是消除上采样的混叠效应(aliasing effect)。
实际上,上图少绘制了一个分支:M5经过步长为2的max pooling下采样得到 P6,作者指出使用P6是想得到更大的anchor尺度512×512。但P6是只用在 RPN中用来得到region proposal的,并不会作为后续Fast RCNN的输入。
总结一下,ResNet-FPN作为RPN输入的feature map是P2,P3,P4,P5,P6 ,而作为后续Fast RCNN的输入则是P2,P3,P4,P5。
5、基于表征学习的ReID方法实践
本项目基于以上说明的论文进行实践,数据集时Market1501数据集。针对论文中的Baseline网络GoogleNet进行了替换,实践的Baseline网络为ResNet50模型,同时使用了与训练的方式对论文进行了实践。
5.1、数据集制作软件配置
5.2、 数据集制作
标注完成后执行如下指令:
执行上图的指令后,更改如下数据集得到类似coco数据集的属于自己的数据集:
5.3、数据增广
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
import randomimport torch
import torchvision
from torchvision.transforms import functional as Fclass Compose(object):def __init__(self, transforms):self.transforms = transformsdef __call__(self, image, target):for t in self.transforms:image, target = t(image, target)return image, targetdef __repr__(self):format_string = self.__class__.__name__ + "("for t in self.transforms:format_string += "\n"format_string += " {0}".format(t)format_string += "\n)"return format_stringclass Resize(object):def __init__(self, min_size, max_size):if not isinstance(min_size, (list, tuple)):min_size = (min_size,)self.min_size = min_sizeself.max_size = max_size# modified from torchvision to add support for max sizedef get_size(self, image_size):w, h = image_sizesize = random.choice(self.min_size)max_size = self.max_sizeif max_size is not None:min_original_size = float(min((w, h)))max_original_size = float(max((w, h)))if max_original_size / min_original_size * size > max_size:size = int(round(max_size * min_original_size / max_original_size))if (w <= h and w == size) or (h <= w and h == size):return (h, w)if w < h:ow = sizeoh = int(size * h / w)else:oh = sizeow = int(size * w / h)return (oh, ow)def __call__(self, image, target=None):size = self.get_size(image.size)image = F.resize(image, size)if target is None:return imagetarget = target.resize(image.size)return image, targetclass RandomHorizontalFlip(object):def __init__(self, prob=0.5):self.prob = probdef __call__(self, image, target):if random.random() < self.prob:image = F.hflip(image)target = target.transpose(0)return image, targetclass RandomVerticalFlip(object):def __init__(self, prob=0.5):self.prob = probdef __call__(self, image, target):if random.random() < self.prob:image = F.vflip(image)target = target.transpose(1)return image, targetclass ColorJitter(object):def __init__(self,brightness=None,contrast=None,saturation=None,hue=None,):self.color_jitter = torchvision.transforms.ColorJitter(brightness=brightness,contrast=contrast,saturation=saturation,hue=hue,)def __call__(self, image, target):image = self.color_jitter(image)return image, targetclass ToTensor(object):def __call__(self, image, target):return F.to_tensor(image), targetclass Normalize(object):def __init__(self, mean, std, to_bgr255=True):self.mean = meanself.std = stdself.to_bgr255 = to_bgr255def __call__(self, image, target=None):if self.to_bgr255:image = image[[2, 1, 0]] * 255image = F.normalize(image, mean=self.mean, std=self.std)if target is None:return imagereturn image, target
5.4、FPN网络模型
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
import torch
import torch.nn.functional as F
from torch import nnclass FPN(nn.Module):"""Module that adds FPN on top of a list of feature maps.The feature maps are currently supposed to be in increasing depthorder, and must be consecutive"""def __init__(self, in_channels_list, out_channels, conv_block, top_blocks=None):"""Arguments:in_channels_list (list[int]): number of channels for each feature map thatwill be fedout_channels (int): number of channels of the FPN representationtop_blocks (nn.Module or None): if provided, an extra operation willbe performed on the output of the last (smallest resolution)FPN output, and the result will extend the result list"""super(FPN, self).__init__()self.inner_blocks = []self.layer_blocks = []for idx, in_channels in enumerate(in_channels_list, 1):inner_block = "fpn_inner{}".format(idx)layer_block = "fpn_layer{}".format(idx)if in_channels == 0:continueinner_block_module = conv_block(in_channels, out_channels, 1)layer_block_module = conv_block(out_channels, out_channels, 3, 1)self.add_module(inner_block, inner_block_module)self.add_module(layer_block, layer_block_module)self.inner_blocks.append(inner_block)self.layer_blocks.append(layer_block)self.top_blocks = top_blocksdef forward(self, x):"""Arguments:x (list[Tensor]): feature maps for each feature level.Returns:results (tuple[Tensor]): feature maps after FPN layers.They are ordered from highest resolution first."""last_inner = getattr(self, self.inner_blocks[-1])(x[-1])results = []results.append(getattr(self, self.layer_blocks[-1])(last_inner))for feature, inner_block, layer_block in zip(x[:-1][::-1], self.inner_blocks[:-1][::-1], self.layer_blocks[:-1][::-1]):if not inner_block:continueinner_top_down = F.interpolate(last_inner, scale_factor=2, mode="nearest")inner_lateral = getattr(self, inner_block)(feature)# TODO use size instead of scale to make it robust to different sizes# inner_top_down = F.upsample(last_inner, size=inner_lateral.shape[-2:],# mode='bilinear', align_corners=False)last_inner = inner_lateral + inner_top_downresults.insert(0, getattr(self, layer_block)(last_inner))if isinstance(self.top_blocks, LastLevelP6P7):last_results = self.top_blocks(x[-1], results[-1])results.extend(last_results)elif isinstance(self.top_blocks, LastLevelMaxPool):last_results = self.top_blocks(results[-1])results.extend(last_results)return tuple(results)class LastLevelMaxPool(nn.Module):def forward(self, x):return [F.max_pool2d(x, 1, 2, 0)]class LastLevelP6P7(nn.Module):"""This module is used in RetinaNet to generate extra layers, P6 and P7."""def __init__(self, in_channels, out_channels):super(LastLevelP6P7, self).__init__()self.p6 = nn.Conv2d(in_channels, out_channels, 3, 2, 1)self.p7 = nn.Conv2d(out_channels, out_channels, 3, 2, 1)for module in [self.p6, self.p7]:nn.init.kaiming_uniform_(module.weight, a=1)nn.init.constant_(module.bias, 0)self.use_P5 = in_channels == out_channelsdef forward(self, c5, p5):x = p5 if self.use_P5 else c5p6 = self.p6(x)p7 = self.p7(F.relu(p6))return [p6, p7]
5.5、图片测试结果
5.6、视频测试结果展示
参考:
https://zhuanlan.zhihu.com/p/37998710
https://zhuanlan.zhihu.com/p/25954683
https://zhuanlan.zhihu.com/p/66973573
https://github.com/facebookresearch/maskrcnn-benchmark
上述内容,如有侵犯版权,请联系作者,会自行删文。
推荐阅读:
吐血整理|3D视觉系统化学习路线
那些精贵的3D视觉系统学习资源总结(附书籍、网址与视频教程)
超全的3D视觉数据集汇总
大盘点|6D姿态估计算法汇总(上)
大盘点|6D姿态估计算法汇总(下)
机器人抓取汇总|涉及目标检测、分割、姿态识别、抓取点检测、路径规划
汇总|3D点云目标检测算法
汇总|3D人脸重建算法
那些年,我们一起刷过的计算机视觉比赛
总结|深度学习实现缺陷检测
深度学习在3-D环境重建中的应用
汇总|医学图像分析领域论文
大盘点|OCR算法汇总
重磅!3DCVer-知识星球和学术交流群已成立
3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导,650+的星球成员为创造更好的AI世界共同进步,知识星球入口:
学习3D视觉核心技术,扫描查看介绍,3天内无条件退款
圈里有高质量教程资料、可答疑解惑、助你高效解决问题
欢迎加入我们公众号读者群一起和同行交流,目前有3D视觉、CV&深度学习、SLAM、三维重建、点云后处理、自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。
▲长按加群或投稿
【项目实践】基于Mask R-CNN的道路物体检测与分割(从数据集制作到视频测试)...相关推荐
- 【笔记】基于 Mask R-CNN 的玉米田间杂草检测方法
<基于 Mask R-CNN 的玉米田间杂草检测方法> 单位:山东农业大学信息科学与工程学院 作者:姜红花 数据获取 相机:Intel RealSense Depth CameraD435 ...
- 【项目实践】车距+车辆+车道线+行人检测项目实践
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自 | AI算法与图像处理 1.项目流程的简介 项目的主题框 ...
- 【项目实践】YOLO V4万字原理详细讲解并训练自己的数据集(pytorch完整项目打包下载)...
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 目录 1.什么是YOLOV4 2.YOLOV4结构解析 2 ...
- 【Pytorch神经网络理论篇】 33 基于图片内容处理的机器视觉:目标检测+图片分割+非极大值抑制+Mask R-CNN模型
基于图片内容的处理任务,主要包括目标检测.图片分割两大任务. 1 目标检测 目标检测任务的精度相对较高,主要是以检测框的方式,找出图片中目标物体所在的位置.目标检测任务的模型运算量相对较小,速度相对较 ...
- 基于尺寸划分的RGB显著物体检测方法
SDCNet: Size Divide and Conquer Network for Salient Object Detection Senbo Yan, Xiaowen Song, and Ch ...
- 二十. 在ROS系统上实现基于PyTorch YOLO v5的实时物体检测
一. 背景介绍 在我前面的博文 十八.在JetsonNano上为基于PyTorch的物体检测网络测速和选型 中,我介绍过在基于Jetson Nano硬件平台和Ubuntu 18.04 with Jet ...
- CODA:自动驾驶中道路目标检测的极端情况数据集
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 来源丨计算机视觉深度学习和自动驾驶 2022年3月arXiv论文"CODA: A Real- ...
- mask rcnn 实例分割的数据集制作
这篇博客是 基于 Google Colab 的 mask rcnn 训练自己的数据集(以实例分割为例)文章中 数据集的制作 这部分的一些补充 温馨提示: 实例分割是针对同一个类别的不同个体或者不同部分 ...
- mask rcnn算法原理图_基于MASK RCNN算法实现瑕疵图像识别(训练模型及应用)
数据的准备其实是最花功夫和时间的,度过了上一个阶段后,就进入激动的模型训练阶段了,首先简要聊聊我对Mask RCNN算法的理解: MaskRCNN是何凯明大神基于FastRCNN的改进,2018年初在 ...
最新文章
- (转)使用 /proc 文件系统来访问 Linux 内核的内容
- python tensorflow tf.layers.max_pooling2d() 2维输入(例如图像)的最大池化层
- caffe模型文件解析_Caffe ImageData神经网络基本示例无法解析模型文件
- RBAC权限模型库表设计
- 使用Red Hat Enterprise Linux的实时内核
- python的lambda函数错误的是_Python 中的 AWS Lambda 函数错误 - AWS Lambda
- Uniswap 24h交易量约为10.6亿美元涨2.91%
- git 代码回滚_谁说用 Git 一定要用命令行?试试 SourceTree 吧
- python 3.6.5 模拟银行转账系统
- 拓端tecdat|R语言使用灰色关联分析(Grey Relation Analysis,GRA)中国经济社会发展指标
- 怎么用Python爬取抖音小视频? 资深程序员都这样爬取的(附源码)
- TOM邮箱容量满了收发不了邮件?你应该快速做到这些事
- 洛谷 P2123 皇后游戏(贪心)
- 浩辰3D软件新手攻略:数据管理功能详解
- 梦想照进现实|CSDN 实体奖牌 第二期
- checkm基因组_checkm8漏洞利用的技术分析
- 在线引流工具Tcpcopy原理、环境搭建、使用、采坑
- 如何快速学习STAR-CCM+软件解决工程实际问题
- 别让灵魂跟不上我们的脚步
- Java 枚举异常的类型