论文阅读 - End-to-End Wireframe Parsing

news2024/10/7 14:21:46

文章目录

  • 1 概述
  • 2 L-CNN
    • 2.1 整体架构
    • 2.2 backbone
    • 2.3 juction proposal module
    • 2.4 line sample module
    • 2.5 line verificatoin module
  • 3 评价指标
  • 参考资料

1 概述

本文是ICCV2019的一篇论文,核心是提出了一种简单的end-to-end的two-stage的检测图像中线段的方法。同时,文章也提出了一种新的评价线段检测效果的指标,这个指标可以惩罚同一个位置有交叠的线段预测,也可以惩罚连接错误的线段。

概括地说,就是一个two-stage的方法L-CNN和一个新的线段评价指标Structural AP(sAP)。

L-CNN可以被分为四个部分:
(1)backbone
用于抽取图像的特征。
(2)juction proposal module
第一阶段中提出节点的proposal的模块,如果这部分有节点没有召回,那后面线段就不可能预测出来了。这是直接影响召回率recall的阶段。
(3)line sample module
负责线段的采样,这是为了给第二阶段提供正负样本进行训练。如果是预测,则认为所有第一节点proposal得到的节点两两相连都作为采样得到的线段。
(4)line verificatoin module
这是第二阶段判断(3)采样得到的线段是否是线段的判别器。这是直接影响精确率precision的阶段。

L-CNN可以吃RGB的输入,然后直接输出线段向量,不需要任何的启发式算法。

在这篇文章之前的论文所使用的评价指标都是像素级别的,认为线段是由独立的像素点集合所构成。本文提出了一种新的线段评价指标sAP,sAP将线段视为一个整体,然后再去计算线段级别的precision和recall。

2 L-CNN

2.1 整体架构

模型的整体架构如下图2-1所示,首先输入RGB图片,图片会经过backbone抽取特征得到一张feature map;feature map经过一些卷积会得到junction heatmap,这个heatmap是模型判断该位置是节点的候选概率图;根据节点的候选概率图,line sampler会sample线段,作为可能存在的线段输入下个模块;最后通过line verification模块来判断sample出来的线段是不是真的线段,每条sample出来的线段会根基feature map得到该线段的特征,再进入判别器进行判别。

最终的输出是节点的位置,以及表示节点之间是否相连的矩阵。

整个网络可以通过SGD进行end-to-end的训练。

L-CNN网络结构图

图2-1 L-CNN网络结构图

2.2 backbone

backbone需要抽取到图片中线段的特征,本文选取的是stacked hourglass network,这是在关键点检测中经常使用的backbone,在这里用来抽取节点和线段的特征非常合适。

stacked hourglass network的Loss即是其他所有模块的Loss之和,也就是其他的模块损失对backbone都会造成影响。

2.3 juction proposal module

在进行节点的预测时,会将 H × W H \times W H×W的图片切分为尺寸为 H b × W b H_b \times W_b Hb×Wb的多个bins,也可以理解为grids。每个bin预测是否有节点在这个bin之内,如果这个bin之内有节点,还会预测节点在这个bin当中的相对位置。总的来说,juction proposal module会输出一个节点的概率图 J J J和节点的位置偏移图 O O O

概率图 J J J的GT(ground truth)用数据公式可以表达为

J ( b ) = { 1 ∃ i ∈ V : p i ∈ b , 0 o t h e r w i s e (2-1) J(b) = \begin{cases} 1 &\exists i \in V: \bold{p}_i \in b, \\ 0 &otherwise \end{cases} \tag{2-1} J(b)={10iV:pib,otherwise(2-1)

其中, J J J表示节点概率图; b b b表示某个bin; V V V表示所有真是存在的节点; p i \bold{p}_i pi表示第 i i i个节点的坐标;

O ( b ) = { ( b − p i ) / W b ∃ i ∈ V : p i ∈ b , 0 o t h e r w i s e (2-2) O(b) = \begin{cases} (\bold{b} - \bold{p}_i) / W_b &\exists i \in V: p_i \in b, \\ 0 &otherwise \end{cases} \tag{2-2} O(b)={(bpi)/Wb0iV:pib,otherwise(2-2)

其中, O O O表示相对位置偏移图; b \bold{b} b表示 b b b的中心点坐标;其余同式 ( 2 − 1 ) (2-1) (21)

按这里的表示, b \bold{b} b是可能超出bin的。个人式 ( 2 − 2 ) (2-2) (22)中的 W b W_b Wb应该换成bin的宽度。

从feature map变成 J J J O O O会分别经过 1 × 1 1 \times 1 1×1的卷积。

作者将预测 J J J视为一个分类问题,即每个bin是否有节点的二分类,使用the average binary cross entropy loss。

将预测 O O O视为回归问题,通过sigmoid函数,并减去0.5的偏置,将 O ( b ) O(b) O(b)限制在 [ − 0.5 , 0.5 ) [-0.5, 0.5) [0.5,0.5)的值域内,loss使用的是L2 loss。注意这里在计算loss时,只对有真实节点落在其中的bin进行计算,并在最后取平均。

预测为节点的bin一般不会单独出现,而是像聚类一样成群出现的,只不过真正节点所在的bin分数最高,周围的bin分数低一些。为了去除这些正确的bin附近的bin,作者采用了nms的方法,将bin八邻域的节点进行抑制。这里的nms只需要通过max pool来实现就可以了。

J ′ ( b ) = { J ( b ) J ( b ) = m a x b ′ ∈ N ( b ) J ( b ′ ) 0 o t h e r w i s e J'(b) = \begin{cases} J(b) &J(b)=max_{b' \in N(b)}J(b') \\ 0 &otherwise \end{cases} J(b)={J(b)0J(b)=maxbN(b)J(b)otherwise

其中, N ( b ) N(b) N(b)就是 b b b的八邻域。

最后会根据分数从 J ′ J' J中选择topK个节点作为最终预测的节点 { p ^ i } i = 1 K \{\hat{\bold{p}}_i\}_{i=1}^K {p^i}i=1K

2.4 line sample module

有了 { p ^ i } i = 1 K \{\hat{\bold{p}}_i\}_{i=1}^K {p^i}i=1K,其实我们可以将K个节点之间两两相连的线段作为proposal放入line verificatoin module中进行预测,共有 C K 2 C_K^2 CK2条线段。但是这样大部分的线段都是负样本,正样本在其中的比例太少了,正负样本极度不平衡。这对于模型的训练影响很大。不过预测阶段,直接取 C K 2 C_K^2 CK2条线段进行line verificatoin即可。

为了解决proposal正负样本不平衡的问题,作者突出了静态采样和动态采样两种方案。

静态和动态采样示意图

图2-2 静态和动态采样示意图

图2-2是静态和动态采样的示意图,红色的节点是GT节点,红色的线段是GT线段,绿色的节点是预测的节点,蓝色的线段是proposal的线段。如果没有静态和动态采样,也就是预测时候的采样方式,就是图2-2(d)所示的方式。

(1)静态采样
静态采样,顾名思义,就是不随着模型预测结果发生变化的,因为它是根据GT来进行采样的。这就避免了模型训练初期,一阶段模型不够好,预测的节点大多是错误节点,导致二阶段拿不到正样本的问题。这个RNN当中的teacher forcing有点相似。

静态采样的正样本 S + S^+ S+,就是真实的线段,如图2-2(b)所示。

静态采样的负样本 S − S^- S,是一些难负样本,它在除了 S + S^+ S+之外的,真实节点之间两两相连的线段之间进行选择,选择时,会将所有的真实线段映射到 64 × 64 64 \times 64 64×64的低分辨率二值图中,有真实线段经过的网格点置为1,其余为0,统计待选择的线段在低分辨率二值图中经过的网格点的分数和的平均。最终取分数最高的top 2000条线段作为 S − S^- S,如图2-2©所示。

(2)动态采样
动态采样是根据模型预测的节点进行采样的。图2-2(d)中的 D ∗ D^* D即是所有预测节点之间两两相连的结果。

m i : = a r g min ⁡ j ∣ ∣ p ^ i − p j ∣ ∣ 2 m_i := arg \min_j || \hat{\bold{p}}_i - \bold{p}_j ||_2 mi:=argminj∣∣p^ipj2,表示于预测节点 p ^ i \hat{\bold{p}}_i p^i最接近的真实节点 p m i \bold{p}_{m_i} pmi。如果 p m i \bold{p}_{m_i} pmi p ^ i \hat{\bold{p}}_i p^i之间的L2距离小于 η \eta η,则认为 p ^ i \hat{\bold{p}}_i p^i匹配上了一个真实节点,成为matched。

在所有matched的节点中,如果 p ^ i 1 \hat{\bold{p}}_{i1} p^i1 p ^ i 2 \hat{\bold{p}}_{i2} p^i2对应的 p m i 1 \bold{p}_{m_{i1}} pmi1 p m i 2 \bold{p}_{m_{i2}} pmi2不是同一个点,且 p m i 1 \bold{p}_{m_{i1}} pmi1 p m i 2 \bold{p}_{m_{i2}} pmi2之间的连线属于 S + S^+ S+,那就认为 p ^ i 1 \hat{\bold{p}}_{i1} p^i1 p ^ i 2 \hat{\bold{p}}_{i2} p^i2的连线属于 D + D^+ D+,如图2-2(e)所示。

在所有matched的节点中,如果 p ^ i 1 \hat{\bold{p}}_{i1} p^i1 p ^ i 2 \hat{\bold{p}}_{i2} p^i2对应的 p m i 1 \bold{p}_{m_{i1}} pmi1 p m i 2 \bold{p}_{m_{i2}} pmi2不是同一个点,且 p m i 1 \bold{p}_{m_{i1}} pmi1 p m i 2 \bold{p}_{m_{i2}} pmi2之间的连线属于 S − S^- S,那就认为 p ^ i 1 \hat{\bold{p}}_{i1} p^i1 p ^ i 2 \hat{\bold{p}}_{i2} p^i2的连线属于 D − D^- D,如图2-2(e)所示。

最终从 D + D^+ D+中取 N D + N_{D^+} ND+作为动态采样的正样本,从 D − D^- D中取 N D − N_{D^-} ND作为动态采样的负样本,从 D ∗ D^* D中取 N D ∗ N_{D^*} ND条与 N D + N_{D^+} ND+ N D − N_{D^-} ND不重复的线段,若线段存在于 D + D^+ D+则为正样本,否则是负样本。

总的来说,静态采样有助于模型的前期训练,动态采样可以让模型对预测得到的线段有更正确的判别。

2.5 line verificatoin module

令2.4中采样得到的线段proposal为 { L j } j = 1 M = { ( p j 1 , p j 2 ) } j = 1 M \{L_j\}_{j=1}^M = \{ (\bold{p}_j ^ 1, \bold{p}_j ^ 2) \}_{j=1}^M {Lj}j=1M={(pj1,pj2)}j=1M,每条线段 L j = ( p j 1 , p j 2 ) L_j = (\bold{p}_j ^ 1, \bold{p}_j ^ 2) Lj=(pj1,pj2)对应于backbone中feature map的一些特征,但是每条线段的长度不同,特征向量的长度也就不同了。这与Faster-RCNN中遇到proposal的图片尺寸不一致的问题一样,这里作者也效仿了RoI Pooling,设计了一种LoI Pooling。

LoI Pooling的做法是对 L j L_j Lj线段进行空间上均匀分布的采样,每条线段都采 N p N_p Np个点,每个点的特征是根据点落在feature map上的位置进行双线性插值得到的。如此一来,经过LoI Pooling的每条线段的特征维度都保持了一致。最终将得到的特征concat起来,输入全连接网络进行判别是否是线段。

3 评价指标

在本文之前评价线段预测结果的方法都是 A P H AP^H APH A P H AP^H APH是将GT线段和预测线段都转换为像素,GT对应的像素在预测结果中也被预测为线段,则该像素点就是TP(true positive)了,然后比较像素的precision和recall。这种方式对于下图3-1所示的两种情况不能处理,一种是预测线段交叠的情况,另一种是节点连接错误的情况。因为这些情况下,映射到像素级别的图上的结果是一致的。

主要问题在于,这种方式并没有将线段视作一个整体。
基于heatmap的方式不适用的示例

图3-1 基于heatmap的方式不适用的示例

为了克服上述的缺点,本文提出了structural average precision (sAP)。这个方法是受目标检测的指标启示得出的。sAP中的TP是线段,只有当预测的线段满足式 ( 3 − 1 ) (3-1) (31)的条件时,才认为是TP。

min ⁡ ( u , v ) ∈ E ∣ ∣ p j 1 − p u ∣ ∣ 2 2 + ∣ ∣ p j 2 − p v ∣ ∣ 2 2 ≤ θ (3-1) \min_{(u, v) \in E} || \bold{p}_j^1 - \bold{p}_u ||_2^2 + || \bold{p}_j^2 - \bold{p}_v ||_2^2 \leq \theta \tag{3-1} (u,v)Emin∣∣pj1pu22+∣∣pj2pv22θ(3-1)

通俗地来说就是,预测线段的两个节点距离预期匹配的真实线段的两个节点的距离都小于 θ \theta θ,则认为是TP。

其中, θ \theta θ的取值表示了严格度,本文中取 θ = 5 \theta = 5 θ=5 θ = 10 \theta = 10 θ=10 θ = 15 \theta = 15 θ=15分别进行计算,对应的表示为 s A P 5 sAP^5 sAP5 s A P 10 sAP^{10} sAP10 s A P 15 sAP^{15} sAP15

需要注意的是,一条GT被认为TP过一次,就不能再被认为是TP了,这避免了一条线段被预测为多条线段的问题。

参考资料

[1] End-to-End Wireframe Parsing
[2] https://github.com/zhou13/lcnn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/390640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

192、【动态规划】leetcode ——64. 最小路径和:回溯法+动态规划(C++版本)

题目描述 原题链接&#xff1a;64. 最小路径和 解题思路 &#xff08;1&#xff09;回溯法 分别向右或下进行探查 class Solution { public:int res INT_MAX;void backtracking(vector<vector<int>>& grid, int x, int y, int pathSum) {// 超出边界&…

高可用 - 08 Keepalived集群中Master和Backup角色选举策略

文章目录概述实例说明“weight”值为正数“weight”值为负数总结概述 在Keepalived集群中&#xff0c;其实并没有严格意义上的主、备节点&#xff0c;虽然可以在Keepalived配置文件中设置“state”选项为“MASTER”状态&#xff0c;但是这并不意味着此节点一直就是Master角色。…

Python实现人脸识别,进行视频跟踪打码,羞羞的画面统统打上马赛克

哈喽兄弟们&#xff0c;我是轻松~ 今天我们来实现用Python自动对视频打马赛克前言准备工作代码实战效果展示最后前言 事情是这样的&#xff0c;昨天去表弟家&#xff0c;用了下他的电脑&#xff0c;不小心点到了他硬盘里隐藏的秘密&#xff0c;本来我只需要用几分钟电脑的&…

第一章初识Linux

文章目录Linux简介LInux的应用领域Linux OS和各种发行版的关系Linux和Unix的关系Linux相关环境配置图解VM和Linux的关系Linux自定义分三个区VMware网络连接的三种模式桥接模式NAT模式主机模式VMware快照功能Linux的操作方式Linux的目录结构各种Linux发行版本的常见目录注意事项…

GO进阶(5) 垃圾回收机制

一、前言 1、垃圾回收背景 编程语言通常会使用手动和自动两种方式管理内存&#xff0c;C、C 以及 Rust 等编程语言使用手动的方式管理内存&#xff0c;工程师需要主动申请或者释放内存&#xff1b;而 Python、Ruby、Java 和 Go 等语言使用自动的内存管理系统&#xff0c;一般都…

Java八股——wait、sleep与park

sleep()、wait()、park()都可以使线程进入等待状态&#xff0c;但是3种方式在使用上和功能上都有些不同。 共同点: wait()&#xff0c;wait(long)和sleep(long)的效果都是让当前线程暂时放弃CPU的使用权&#xff0c;进入阻塞状态它们都可以被打断唤醒都是native方法执行sleep…

java四种线程池(基本使用)

标题java四种线程池及使用示例 1、线程工厂 1、我们先来写ThreadFactory&#xff0c;在创建线程池时候可以传入自定义的线程工厂&#xff0c;线程工厂说白了就是用来定制线程的一些属性&#xff1a;名字、优先级、是否为守护线程。直接看代码即可。 当然创建线程池的时候可以…

控制台运行java

控制台执行java 新建java代码 新建一个记事本文件&#xff0c;将文件名改为HelloWorld.java&#xff0c;注意&#xff1a;后缀是.java。 若没有显示文件后缀&#xff0c;可以在资源管理器打开显示后缀&#xff0c;然后再次修改文件名&#xff0c;一定要修改成文件类型是java…

缺陷及缺陷管理

今日目标能够说出缺陷的判定标准能够说出描述缺陷的6大核心内容能够描述缺陷状态、严重程度、优先级的作用能够按照提供的缺陷模版完成一个缺陷的提交能够说出缺陷的跟踪流程能够在禅道中提交测试用例能够在禅道中提交缺陷1. 缺陷1.1 缺陷的定义&#xff08;重点&#xff09;产…

Python3.8.8-Django3.2-Redis-连接池-数据类型-字符串-list-hashmap-命令行操作

文章目录1.认识Redis1.1.优点1.2.缺点2.在Django中Redis的连接3.Redis的基础用法3.1.hashmap结构3.2.list结构4.命令行查看数据库5.作者答疑1.认识Redis Remote DIctionary Server(Redis) 是一个key-value 存储系统&#xff0c;是跨平台的非关系型数据库。是一个开源的使用 AN…

Linux入门篇-Linux目录结构

简介 简单介绍Linux目录。 Linux的⽬录结构 “/”表示根⽬录&#xff0c;根⽬录是Linux⽬录结构中的最顶级的⽬录&#xff0c;类似于windows的C:\ D:\ /boot⽬录&#xff1a;存放的是系统的启动配置⽂件和内核⽂件 /dev⽬录&#xff1a;存放的是Linux的设备⽂件 /etc⽬录&…

Nacos新手详细知识大全

官网&#xff1a;Spring Cloud Alibaba一、Nacos快速入门1.1 服务注册到Nacos1.1.1 配置**引入com.alibaba.cloud&#xff0c;**以后的版本就不用操心了<!-- com.alibaba.cloud--><!-- com.alibaba.cloud--><dependency><groupId>com.alibaba.cloud<…

SpringCloud之 LoadBalancer负载均衡

文章目录LoadBalancer 负载均衡一、LoadBalanced 负载均衡二、自定义负载均衡三、OpenFeign 实现负载均衡①添加依赖②启动类添加 EnableFeignClients③创建客户端接口 UserClient④service业务中调用客户端接口提示&#xff1a;以下是本篇文章正文内容&#xff0c;SpringCloud…

pv和pvc

一、PV和PVC详解当前&#xff0c;存储的方式和种类有很多&#xff0c;并且各种存储的参数也需要非常专业的技术人员才能够了解。在Kubernetes集群中&#xff0c;放了方便我们的使用和管理&#xff0c;Kubernetes提出了PV和PVC的概念&#xff0c;这样Kubernetes集群的管理人员就…

【Python】torch.einsum()解析

【Python】torch.einsum()解析 文章目录【Python】torch.einsum()解析1. 介绍2. 示例2.1 Pytorch矩阵乘法2.2 Numpy高阶张量3. 参考1. 介绍 爱因斯坦简记法&#xff1a;是一种由爱因斯坦提出的&#xff0c;对向量、矩阵、张量的求和运算 ∑\sum∑ 的求和简记法。在该简记法当中…

链表面试题

链表面试题1. 删除链表中等于给定值 val 的所有结点。2. 反转一个单链表。3. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。4. 输入一个链表&#xff0c;输出该链表中倒数第k个结点。5. 将两个有…

延时任务的四种实现方式

什么是延迟任务&#xff1f;顾明思议&#xff0c;我们把需要延迟执行的任务叫做延迟任务。延迟任务的使用场景有以下这些&#xff1a;红包 24 小时未被查收&#xff0c;需要延迟执退还业务&#xff1b;每个月账单日&#xff0c;需要给用户发送当月的对账单&#xff1b;订单下单…

计算机网络之MAC和IP地址

MAC地址 在局域网中&#xff0c;硬件地址&#xff0c;又称为物理地址或MAC地址。 目前现在的局域网中实际上使用的都是6字节的MAC地址&#xff0c;所以每一个以太网设备都具有唯一的MAC地址。 MAC地址的格式 假设传输使用的是IP数据&#xff0c;V2的MAC帧较为简单&#xff…

Sonar:VSCode配置SonarLint/SonarLint连接SonarQube

需求描述 公司为项目代码配置了Sonar检测&#xff0c;希望在VSCode中开发项目时能够同步检测结果。 注意事项 SonarQube版本必须为7.9&#xff0c;否则SonarLint无法连接&#xff08;GitHub-SonarLint-Wiki第一行就有说明&#xff09;&#xff01;&#xff01;&#xff01;S…

【前端】一个更底层库-React基础知识点第2篇

目录属性状态PROPSPROP VALIDATIONSTATEFORMCONTROLLED COMPONENTSMIXINCOMPONENT APICOMPONENT LIFECYCLETOP API上一篇文章也是React基础知识点&#xff0c;了解到了React是什么&#xff1f;为什么要使用React&#xff1f;还知道了JSX概述&#xff0c;JSX嵌入变量&#xff0c…