得到按钮句柄后如何点集_RepPoint:可形变卷积生成的目标轮廓点集
论文题目为: RepPoints: Point Set Representation for Object Detection
idea总结:
- 改变目标检测领域中对于目标用矩形框的表现形式,而是采用点集的形式来表现一个物体的轮廓
- 特征抽取后,配合deformable convolution来进对物体中心点的偏移量学习,得到其点集的位置.
- 提出三种转换方式,将点集转化为矩形框方便评测该目标检测算法的指标
respoints 表示
传统目标检测采用一个4-D的向量来表示一个物体
respoint则是用一组点集来表示,其中n代表了取样点的数量(文中设置为9).建议为某个数的平方
如图表示,respints在backbone骨干网络抽取特征后,通过其RepPointsHead结构转化成9个物体的轮廓点,然后,这9个点形成物体边框的pseudo box,然后再转化为传统目标检测的bbox.
回顾传统的多阶段目标检测
传统的两阶段目标检测流程:
- 通过预设的锚点(anchor)来覆盖一定范围的边界框比例和纵横比.
- 对于锚点,将其中心点处的图像特征作为对象特征,生成有关锚点是否为目标对象的置信度得分,并通过边界框回归生成精炼的边界框(bbox proposals)
- 在第二阶段,通过 RoI-pooling 或 RoI-Align从(2)中获得的边界框建议提取对象特征.
- 经过改进的特征将通过边界框回归产生最终的边界框目标。
- 对于多阶段方法,还通过边界框回归,使用改进的特征来生成中间的改进的边界框建议(S2)。在生成最终的边界框目标之前,可以多次重复此步骤,用以修正目标框边界.
边界框与点集回归对比
逐步完善边界框定位和特征提取对于多阶段目标检测方法的成功至关重要。
对于bbox表现形式:
4-d的回归量
对于ground truth bounding box
对于respoint形式
所以我们只需要学习其offset,然后加到原始点坐标即可.
RPDet:anchor free的respoint 检测器
其流程如下图所示:
- 使用中心点作为对象的初始表示.
- 基于中心点,通过deformable convolution 来学习每个中心点的偏移量,如9个点偏移量来表示物体,则用一个3 X 3的可变形卷积.然后利用偏移量对物体位置进行回归.
- 经过两次deformable convolution的offset偏移量回归矫正,形成respints object
其RPDet的head主要算法结构如图所示:
其中locate subnet 与class subnet两个子网络的输入都是通过rpn主干网络抽取的相同图像特征.
我们看到通过center point生成respoint的奥秘在于locate subnet中那个 3 X 3 的可变形卷积自动学习得到的关于物体的感受野位置
respoint 生成bbox的三种方法:
- Min-max function.在RepPoints上执行两个轴上的Min-max操作以确定Bp,等效于所有采样点上的边界框值.
- Partial min-max function.在两个轴上分别对样本点的子集进行最小-最大运算,以获得矩形框值.
- Moment-based function.RepPoints的平均值和标准偏差用于计算矩形框Bp的中心点和比例,其中比例与全球共享的可学习乘数λx和λy相乘。(代码中默认使用这种方式)
loss的计算:
- location loss:先将respoint转换为伪框(pseudo box),然后计算pseudo box与ground- truth bounding box的loss.(论文中使用左上角与右下角之间的smooth l1 loss来得到location loss)
- classification loss:采用FocalLoss的形式来解决类别不平衡问题
代码分析
RPDet的代码在https://github.com/microsoft/RepPoints.已合并如mmdetion框架中,我们来看mmdetion中的代码:
config文件: config/reppoints/reppoints_moment_r50_fpn_1x.py
#model定义
model = dict(type='RepPointsDetector',pretrained='torchvision://resnet50',backbone=dict(type='ResNet',depth=50,num_stages=4,out_indices=(0, 1, 2, 3),frozen_stages=1,style='pytorch'),neck=dict(type='FPN',in_channels=[256, 512, 1024, 2048],out_channels=256,start_level=1,add_extra_convs=True,num_outs=5,norm_cfg=norm_cfg),bbox_head=dict(type='RepPointsHead',num_classes=81,in_channels=256,feat_channels=256,point_feat_channels=256,stacked_convs=3,num_points=9,gradient_mul=0.1,point_strides=[8, 16, 32, 64, 128],point_base_scale=4,norm_cfg=norm_cfg,loss_cls=dict(type='FocalLoss',use_sigmoid=True,gamma=2.0,alpha=0.25,loss_weight=1.0),loss_bbox_init=dict(type='SmoothL1Loss', beta=0.11, loss_weight=0.5),loss_bbox_refine=dict(type='SmoothL1Loss', beta=0.11, loss_weight=1.0),transform_method='moment'))
其主干网络采用restnet+fpn的形式,正常的多尺度抽取图像特征;
下面我们结合reppoint-head的结构图,来看两个subnet是如何发挥作用的: mmdet/models/anchor_heads/resppoints_head.py
@HEADS.register_module
class RepPointsHead(nn.Module):def __init__(self,****)
#部分省略初始化定义# we use deformable conv to extract points features#dcn的kernel大小即为定义点的数量,即用一个dcn的感受野来表示物体轮廓self.dcn_kernel = int(np.sqrt(num_points))self.dcn_pad = int((self.dcn_kernel - 1) / 2)assert self.dcn_kernel * self.dcn_kernel == num_points, "The points number should be a square number."assert self.dcn_kernel % 2 == 1, "The points number should be an odd square number."#可变形卷积的初始化x,y偏移量dcn_base = np.arange(-self.dcn_pad,self.dcn_pad + 1).astype(np.float64)dcn_base_y = np.repeat(dcn_base, self.dcn_kernel)dcn_base_x = np.tile(dcn_base, self.dcn_kernel)dcn_base_offset = np.stack([dcn_base_y, dcn_base_x], axis=1).reshape((-1))self.dcn_base_offset = torch.tensor(dcn_base_offset).view(1, -1, 1, 1)self._init_layers()def _init_layers(self):self.relu = nn.ReLU(inplace=True)self.cls_convs = nn.ModuleList()self.reg_convs = nn.ModuleList()#两个subnet分别都有3个3X3的卷积进行特征抽取工作for i in range(self.stacked_convs):chn = self.in_channels if i == 0 else self.feat_channelsself.cls_convs.append(ConvModule(chn,self.feat_channels,3,stride=1,padding=1,conv_cfg=self.conv_cfg,norm_cfg=self.norm_cfg))self.reg_convs.append(ConvModule(chn,self.feat_channels,3,stride=1,padding=1,conv_cfg=self.conv_cfg,norm_cfg=self.norm_cfg))#respoint利用dcn进行offset学习部分网络定义pts_out_dim = 4 if self.use_grid_points else 2 * self.num_pointsself.reppoints_cls_conv = DeformConv(self.feat_channels,self.point_feat_channels,self.dcn_kernel, 1, self.dcn_pad)self.reppoints_cls_out = nn.Conv2d(self.point_feat_channels,self.cls_out_channels, 1, 1, 0)self.reppoints_pts_init_conv = nn.Conv2d(self.feat_channels,self.point_feat_channels, 3,1, 1)self.reppoints_pts_init_out = nn.Conv2d(self.point_feat_channels,pts_out_dim, 1, 1, 0)self.reppoints_pts_refine_conv = DeformConv(self.feat_channels,self.point_feat_channels,self.dcn_kernel, 1,self.dcn_pad)self.reppoints_pts_refine_out = nn.Conv2d(self.point_feat_channels,pts_out_dim, 1, 1, 0)#网络前馈计算def forward_single(self, x):dcn_base_offset = self.dcn_base_offset.type_as(x)# If we use center_init, the initial reppoints is from center points.# If we use bounding bbox representation, the initial reppoints is# from regular grid placed on a pre-defined bbox.if self.use_grid_points or not self.center_init:scale = self.point_base_scale / 2points_init = dcn_base_offset / dcn_base_offset.max() * scalebbox_init = x.new_tensor([-scale, -scale, scale,scale]).view(1, 4, 1, 1)else:points_init = 0cls_feat = xpts_feat = xfor cls_conv in self.cls_convs:cls_feat = cls_conv(cls_feat)for reg_conv in self.reg_convs:pts_feat = reg_conv(pts_feat)# initialize reppointspts_out_init = self.reppoints_pts_init_out(self.relu(self.reppoints_pts_init_conv(pts_feat)))if self.use_grid_points:pts_out_init, bbox_out_init = self.gen_grid_from_reg(pts_out_init, bbox_init.detach())else:pts_out_init = pts_out_init + points_init# refine and classify reppointspts_out_init_grad_mul = (1 - self.gradient_mul) * pts_out_init.detach() + self.gradient_mul * pts_out_initdcn_offset = pts_out_init_grad_mul - dcn_base_offsetcls_out = self.reppoints_cls_out(self.relu(self.reppoints_cls_conv(cls_feat, dcn_offset)))pts_out_refine = self.reppoints_pts_refine_out(self.relu(self.reppoints_pts_refine_conv(pts_feat, dcn_offset)))if self.use_grid_points:pts_out_refine, bbox_out_refine = self.gen_grid_from_reg(pts_out_refine, bbox_out_init.detach())else:pts_out_refine = pts_out_refine + pts_out_init.detach()return cls_out, pts_out_init, pts_out_refine
总结与tips
这篇论文在我的理解中,更像是将可形变卷积应用在了目标检测领域,通过定位和分类的监督loss来监督可形变卷积对于物体偏移量的学习,使得卷积的学习变得可解释性.启发我们可以可以用不同的监督信息来使用可形变卷积.
respoint 如何解决同一位置多个物体的遮挡问题:
In RPDet, we show that this issue can be greatly alleviated by using the FPN structure [24] for the following reasons: first, objects of different scales will be assigned to different image feature levels, which addresses objects of different scales and the same center points locations; second, FPN has a high-resolution feature map for small objects, which also reduces the chance of two objects having centers located at the same feature position.
作者认为通过rpn结构将不同比例对象分配给不同的图像特征的方式来解决;
但这种方式能放解决像行人检测中多个行人遮挡问题还有待商榷.
得到按钮句柄后如何点集_RepPoint:可形变卷积生成的目标轮廓点集相关推荐
- win10移动热点按钮打开后立刻自动关闭
win10移动热点按钮打开后立刻自动关闭 问题如图: 解决措施 Win+R,输入services.msc(或者打开任务管理器,点开"详细信息",找到顶部的"服务" ...
- python 实现读取excel中的所有sheet后,增加新的sheet,生成新的excel文件
python 实现读取excel中的所有sheet后,增加新的sheet,生成新的excel文件 import pandas as pd import osPath = r"C:\Users ...
- CAD/CASS遮罩分图:带状图批量分幅,可依据闭合线批量分图,支持自定义图框,分图后可批量打印,可批量生成布局
插件下载:QTools for AutoCAD 功能位置:qq或qtools命令==>杂项==>遮罩分图(或直接ft命令) 功能介绍: 带状图批量分幅,可依据闭合线批量分图,支持自定义图框 ...
- layui图片上传按钮按着没反应_关于layui动态生成文件上传按钮后点击无效的解决办法...
首先,这是一个坑,大坑,网上一大堆写的云里雾里,不知所以,转了一圈,除了copy就是copy,Jesus God,花了一晚上,走通了这个坑,话不多说,直接解决 layui版本: layui-v2.5. ...
- 提交按钮提交后页面自动刷新
在表单的提交按钮如果没有type属性,在点击提交按钮后页面会自动刷新,导致使用js改变的页面元素被刷新掉了 <button type="submit" style=" ...
- 关于Java按钮添加后要等鼠标滑过才会显示的问题
之前在开发程序的时候遇到一个问题,就是在窗口的面板里添加JBtton后但窗口显示时,按钮不显示,要等鼠标滑过按钮上面时才显示出来,根据这个问题我发了个帖子寻求大神帮忙,遇到一个大神指点了一下,他说我可 ...
- C++ 通过查找按钮句柄激活另外程序按钮 窗口函数EnumchildWindow,EnableWindow,setwindowpos用法
#include<iostream> #include<cstring> #include<Windows.h>//注意程序要用管理员权限打开,否则如果要查找的程序 ...
- ajax修改按钮的html值,表格行的按钮AJAX后,怎么修改表格当前行的值
field: 'operate', title: __('Operate'), buttons: [ { name: 'commit', title: "提交审核", text: ...
- ajas php 验证码_thinkPHP3.2.3利用Ajax前台实现验证码验证,但通过form表单的按钮提交后,验证码一直错误!如何解决?...
展开全部 我用的方法是判断$_session里的验证码值是否与post提交的验证码值是否相等,经过测试没有问636f707962616964757a686964616f31333363396432题, ...
最新文章
- 一线大厂的分布式唯一ID生成方案是什么样的?
- android应用测试机型,app兼容测试选择哪些机型才够全面呢?
- MYSQL——常用运算符和函数
- 利用angular4和nodejs-express构建一个简单的网站(九)—用户登录
- docker 安装nginx 配置目录挂载
- 中山大学 精品课程C++ 视频教学 共51讲
- leetcode113. 路径总和 II(dfs)
- Linux学习笔记--导航(CentOS 7)
- python生成安装程序_python生成安装文件 msi
- (转) QImage总结
- wsl使用ssh连接
- 前端实现html转pdf方法总结
- 今日做题家 - 面试算法题教程系列总纲
- vs2010格式化html,VS中的快捷键快速格式化代码,使好看,整齐
- Nature、Science、Cell、Plos系列顶级学术杂志解析
- 计算机技术 安防 工程师考试,信息安全工程师考试科目有哪几门
- 电脑如何设置定时关机?
- Abaqus应力结点数据导出与处理
- Word保存高清图片
- SecureCRT 注册机使用方法
热门文章
- Angular 依赖注入的一个常见错误 NullInjectorError, No provider for XXX
- SAP Spartacus TypeScript和编译后的JavaScript命名规范
- JSP项目报错在build path里找不到javax.servlet.http.HttpServlet的解决方法
- 如何给Wordpress安装插件
- why always SAP WebContent is added as prefix of url when repository request ser
- Tomcat 是怎么处理js file access request的
- 研究partner determination的逻辑能否抽出来,以API的形式被我们Odata service implementation code里调用?
- employee setup in Organization unit
- 根据变量值取得变量的参数名
- 为什么SAP UI5框架在应用整个生命周期只调用onBeforeRendering一次