轮廓检测_轮廓检测| Richer Convolutional Features | CVPR | 2017

d9b9d7760784b89ae4e7ba9536296c02.png

0 概述

  • 论文名称:“Richer Convolutional Features for Edge Detection”
  • 论文链接:https://openaccess.thecvf.com/content_cvpr_2017/papers/Liu_Richer_Convolutional_Features_CVPR_2017_paper.pdf
  • 缩写:RCF

这一篇文论在我看来,是CVPR 2015年 HED网络(holistically-nested edge detection)的一个改进,RCF的论文中也基本上和HED网络处处对比

在上一篇文章中,我们依稀记得HED模型有这样一个图:

370b293157a75a105cc5e802b23f80cb.png

其中有HED的五个side output的特征图,下图是RCF论文中的图:

574654a690966c30ea44cac0cdd034bc.png

我们从这两个图的区别中来认识RCF相比HED的改进,大家可以看一看图。

揭晓答案:

  • HED是豹子的图片,但是RCF是两只小鸟的图片(手动狗头)
  • HED中的是side output的输出的特征图,而RCF中是conv3_1,conv3_2,这意味着RCF似乎把每一个卷积之后的输出的特征图都作为了一个side output

没错,HED选取了5个side output,每一个side output都是池化层之前的卷积层输出的特征图;而RCF则对每一次卷积的输出特征图都作为side output,换句话说 最终的side output中,同一尺寸的输出可能不止一个

如果还没有理解,请看下面章节,模型结构。

1 模型结构

RCF的backbone是VGG模型:

f2978a6c12d46fe9765ebf87b1cc9455.png

从图中可以看到:

  • 主干网络上分成state1到5,stage1有两个卷积层,stage2有两个卷积层,总共有13个卷积层,每一次卷积输出的图像,再额外接入一个1x1的卷积,来降低通道数,所以可以看到,图中有大量的21通道的卷积层。
  • 同一个stage的21通道的特征图经过通道拼接,变成42通道或者是63通道的特征图,然后再经过一个1x1的卷积层,来把通道数降低成1,再进过sigmoid层,输出的结果就是一个RCF模型中的side output了

2 损失函数

这里的损失函数其实和HED来说类似:

ddc933691abb27917f0c87a5c19f97a9.png

首先整体来看,损失函数依然使用二值交叉熵

e337af37d778cc70a5c2f5576b2319ff.png

其中

表示 negative的像素值,
表示positive的像素值。
一般来说轮廓检测任务中,positive的样本应该是较少的,因此
的值较小,因此损失函数中第一行,y=0也就是计算非轮廓部分的损失的时候,就会增加一个较小的权重,来避免类别不均衡的问题。

损失函数中有两个常数,一个是

,这个就是权重常数,默认为1.1;另外一个是
。论文中的描述为:
Edge datasets in this community are usually labeled by several annotators using their knowledge about the presences of objects and object parts. Though humans vary in cognition, these human-labeled edges for the same image share high consistency. For each image, we average all the ground truth to generate an edge probability map, which ranges from 0 to 1. Here, 0 means no annotator labeled at this pixel, and 1 means all annotators have labeled at this pixel. We consider the pixels with edge probability higher than η as positive samples and the pixels with edge probability equal to 0 as negative samples. Otherwise, if a pixel is marked by fewer than η of the annotators, this pixel may be semantically controversial to be an edge point. Thus, whether regarding it as positive or negative samples may confuse networks. So we ignore pixels in this category.

大意就是:一般对数据集进行标注,是有多个人来完成的。不同的人虽然有不同的意识,但是他们对于同一个图片的轮廓标注往往是具有一致性。RCF网络最后的输出,是由5个side output融合产生的,因此你这个RCF的输出也应该把大于

的考虑为positive,然后小于
的考虑为negative。
其实这一点我自己在复现的时候并没有考虑,我看网上的github和官方的代码中,都没有考虑这个,都是直接交叉熵。。。我这就也就多此一举的讲解一下论文中的这个
的含义

3 pytorch部分代码

对于这个RCF论文来说,关键就是一个模型的构建,另外一个就是损失函数的构建,这里放出这两部分的代码,来帮助大家更好的理解上面的内容。

3.1 模型部分

下面的代码在上采样部分的写法比较老旧,因为这个网上找来的pytorch版本估计比较老,当时还没有Conv2DTrans这样的函数封装,但是不妨碍大家通过代码来学习RCF。

class RCF(nn.Module):def __init__(self):super(RCF, self).__init__()#lr 1 2 decay 1 0self.conv1_1 = nn.Conv2d(3, 64, 3, padding=1)self.conv1_2 = nn.Conv2d(64, 64, 3, padding=1)self.conv2_1 = nn.Conv2d(64, 128, 3, padding=1)self.conv2_2 = nn.Conv2d(128, 128, 3, padding=1)self.conv3_1 = nn.Conv2d(128, 256, 3, padding=1)self.conv3_2 = nn.Conv2d(256, 256, 3, padding=1)self.conv3_3 = nn.Conv2d(256, 256, 3, padding=1)self.conv4_1 = nn.Conv2d(256, 512, 3, padding=1)self.conv4_2 = nn.Conv2d(512, 512, 3, padding=1)self.conv4_3 = nn.Conv2d(512, 512, 3, padding=1)self.conv5_1 = nn.Conv2d(512, 512, kernel_size=3,stride=1, padding=2, dilation=2)self.conv5_2 = nn.Conv2d(512, 512, kernel_size=3,stride=1, padding=2, dilation=2)self.conv5_3 = nn.Conv2d(512, 512, kernel_size=3,stride=1, padding=2, dilation=2)self.relu = nn.ReLU()self.maxpool = nn.MaxPool2d(2, stride=2, ceil_mode=True)self.maxpool4 = nn.MaxPool2d(2, stride=1, ceil_mode=True)#lr 0.1 0.2 decay 1 0self.conv1_1_down = nn.Conv2d(64, 21, 1, padding=0)self.conv1_2_down = nn.Conv2d(64, 21, 1, padding=0)self.conv2_1_down = nn.Conv2d(128, 21, 1, padding=0)self.conv2_2_down = nn.Conv2d(128, 21, 1, padding=0)self.conv3_1_down = nn.Conv2d(256, 21, 1, padding=0)self.conv3_2_down = nn.Conv2d(256, 21, 1, padding=0)self.conv3_3_down = nn.Conv2d(256, 21, 1, padding=0)self.conv4_1_down = nn.Conv2d(512, 21, 1, padding=0)self.conv4_2_down = nn.Conv2d(512, 21, 1, padding=0)self.conv4_3_down = nn.Conv2d(512, 21, 1, padding=0)self.conv5_1_down = nn.Conv2d(512, 21, 1, padding=0)self.conv5_2_down = nn.Conv2d(512, 21, 1, padding=0)self.conv5_3_down = nn.Conv2d(512, 21, 1, padding=0)#lr 0.01 0.02 decay 1 0self.score_dsn1 = nn.Conv2d(21, 1, 1)self.score_dsn2 = nn.Conv2d(21, 1, 1)self.score_dsn3 = nn.Conv2d(21, 1, 1)self.score_dsn4 = nn.Conv2d(21, 1, 1)self.score_dsn5 = nn.Conv2d(21, 1, 1)#lr 0.001 0.002 decay 1 0self.score_final = nn.Conv2d(5, 1, 1)def forward(self, x):# VGGimg_H, img_W = x.shape[2], x.shape[3]conv1_1 = self.relu(self.conv1_1(x))conv1_2 = self.relu(self.conv1_2(conv1_1))pool1   = self.maxpool(conv1_2)conv2_1 = self.relu(self.conv2_1(pool1))conv2_2 = self.relu(self.conv2_2(conv2_1))pool2   = self.maxpool(conv2_2)conv3_1 = self.relu(self.conv3_1(pool2))conv3_2 = self.relu(self.conv3_2(conv3_1))conv3_3 = self.relu(self.conv3_3(conv3_2))pool3   = self.maxpool(conv3_3)conv4_1 = self.relu(self.conv4_1(pool3))conv4_2 = self.relu(self.conv4_2(conv4_1))conv4_3 = self.relu(self.conv4_3(conv4_2))pool4   = self.maxpool4(conv4_3)conv5_1 = self.relu(self.conv5_1(pool4))conv5_2 = self.relu(self.conv5_2(conv5_1))conv5_3 = self.relu(self.conv5_3(conv5_2))conv1_1_down = self.conv1_1_down(conv1_1)conv1_2_down = self.conv1_2_down(conv1_2)conv2_1_down = self.conv2_1_down(conv2_1)conv2_2_down = self.conv2_2_down(conv2_2)conv3_1_down = self.conv3_1_down(conv3_1)conv3_2_down = self.conv3_2_down(conv3_2)conv3_3_down = self.conv3_3_down(conv3_3)conv4_1_down = self.conv4_1_down(conv4_1)conv4_2_down = self.conv4_2_down(conv4_2)conv4_3_down = self.conv4_3_down(conv4_3)conv5_1_down = self.conv5_1_down(conv5_1)conv5_2_down = self.conv5_2_down(conv5_2)conv5_3_down = self.conv5_3_down(conv5_3)so1_out = self.score_dsn1(conv1_1_down + conv1_2_down)so2_out = self.score_dsn2(conv2_1_down + conv2_2_down)so3_out = self.score_dsn3(conv3_1_down + conv3_2_down + conv3_3_down)so4_out = self.score_dsn4(conv4_1_down + conv4_2_down + conv4_3_down)so5_out = self.score_dsn5(conv5_1_down + conv5_2_down + conv5_3_down)## transpose and crop way weight_deconv2 =  make_bilinear_weights(4, 1).cuda()weight_deconv3 =  make_bilinear_weights(8, 1).cuda()weight_deconv4 =  make_bilinear_weights(16, 1).cuda()weight_deconv5 =  make_bilinear_weights(32, 1).cuda()upsample2 = torch.nn.functional.conv_transpose2d(so2_out, weight_deconv2, stride=2)upsample3 = torch.nn.functional.conv_transpose2d(so3_out, weight_deconv3, stride=4)upsample4 = torch.nn.functional.conv_transpose2d(so4_out, weight_deconv4, stride=8)upsample5 = torch.nn.functional.conv_transpose2d(so5_out, weight_deconv5, stride=8)### center cropso1 = crop(so1_out, img_H, img_W)so2 = crop(upsample2, img_H, img_W)so3 = crop(upsample3, img_H, img_W)so4 = crop(upsample4, img_H, img_W)so5 = crop(upsample5, img_H, img_W)fusecat = torch.cat((so1, so2, so3, so4, so5), dim=1)fuse = self.score_final(fusecat)results = [so1, so2, so3, so4, so5, fuse]results = [torch.sigmoid(r) for r in results]return results

3.2 损失函数部分

def cross_entropy_loss_RCF(prediction, label):label = label.long()mask = label.float()num_positive = torch.sum((mask==1).float()).float()num_negative = torch.sum((mask==0).float()).float()mask[mask == 1] = 1.0 * num_negative / (num_positive + num_negative)mask[mask == 0] = 1.1 * num_positive / (num_positive + num_negative)mask[mask == 2] = 0cost = torch.nn.functional.binary_cross_entropy(prediction.float(),label.float(), weight=mask, reduce=False)return torch.sum(cost)

参考文章:

  1. https://blog.csdn.net/a8039974/article/details/85696282
  2. https://gitee.com/HEART1/RCF-pytorch/blob/master/functions.py
  3. https://openaccess.thecvf.com/content_cvpr_2017/papers/Liu_Richer_Convolutional_Features_CVPR_2017_paper.pdf

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

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

相关文章

NodeJS开发环境配置

为什么80%的码农都做不了架构师?>>> 上链接~ http://www.cnblogs.com/Irving/p/3634232.html 转载于:https://my.oschina.net/weiyi/blog/287177

python各种类型转换-int,str,char,float,ord,hex,oct等

int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real [,imag ]) 创建一个复数 str(x ) 将对象 x 转换为字符串 repr(x ) 将对象 x 转换为表达式字符串 eval(str ) 用来计算在字符串中的有效Python表达式,并返…

一个平行四边形可以分成四个_将平行四边形分割成两个三角形还易变形么?(人教四下五单元三角形例2)...

最近,我学了三角形一课,研究了三角形的特性。课上我们拿出准备好的拼搭的三角形和平行四边形,动手拉一拉,结果发现三角形拉不动、平行四边形一拉就变形了。原来动动手也是研究数学呀,太有意思了!这时&#…

Java中利用MessageFormat对象实现类似C# string.Format方法格式化

我们在写C#代码的时候常常会使用到string.Format("待格式化字符串{0},{1},....",参数1,参数2,...),来格式化字符串,特别是拼接字符的时候,这种方式使得代码更为直观清楚。 最近使用java时候却java的string.Format与c#重点string.Fo…

配置redis三主三从

主从环境 centos7.6 redis4.0.1 主从192.168.181.139:6379192.168.181.136:6379192.168.181.136:6380192.168.181.137:6380192.168.181.137:6381192.168.181.139:6381集群实例配置 这里展示192.168.181.139:6379节点的,其他配置修改ip、端口号和文件名 bind 192.168…

加个属性让div成纵向横向无缝滚动(支持IE和FF)

<!doctype html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"> <head> <title>无缝div(纵向,横向滚动)(s…

tensorflow 模型小型化_模型小型化

实习终于结束了&#xff0c;现把实习期间做的基于人体姿态估计的模型小型化的工作做个总结。现在深度学习模型开始走向应用&#xff0c;因此我们需要把深度学习网络和模型部署到一些硬件上&#xff0c;而现有一些模型的参数量由于过大&#xff0c;会导致在一些硬件上的运行速度…

css多行超出时,超出高度,显示省略号

.layoutdisplay: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;转载于:https://www.cnblogs.com/cx709452428/p/10457182.html

设计模式系列漫谈之二 - 工厂方法模式

故事 10月1日是小雪的生日。许多追求者都想在生日那天给小雪一份意想不到的惊喜&#xff0c;并且表达自己的爱意。这些追求者绞尽脑汁的为小雪发送一个比较有创意的祝福短信。看来&#xff0c;小雪今年的生日过得肯定非常幸福。但是&#xff0c;小雪的手机还是比较特别&a…

谁控制了我们的浏览器?

http://www.baidu.com/link?url4Qw_a5JHvJi8NPp7of9HqRWN93EPxC2Vy9CPxm3e-KgcO443jRRS_1jzcWDAF8qf5oPPwipv0D6BRQf5XMNi1a 本文遵从GPL协议&#xff0c;欢迎转载。 1、现象是什么&#xff1f; 大约从今年年初开始&#xff0c;很多人就发现&#xff0c;在浏览一些网站的时候&…

java面试题大全答案版文库_java高级面试题带答案

java高级面试题&#xff0c;java面试题大全带答案&#xff0c;线程面试题&#xff0c;java面试宝典20191、[请对以下在J2EE中常用的名词进行解释(或简单描述)](http://www.wityx.com/post/172_1_1.html)2、[socket通信](http://www.wityx.com/post/175_1_1.html)3、[简述线程的…

SP1693 COCONUTS - 题解

SP1693 COCONUTS 题意&#xff1a; 几个士兵在投票&#xff0c;有支持与反对两种选择&#xff0c;每个人有自己的看法&#xff0c;但是他们有时也会为了支持朋友的看法而放弃自己的看法&#xff0c;请求出一种方案&#xff0c;使得违背自己初始看法的人数与看法不一致的朋友对数…

最近特忙

昨天上午上课&#xff0c;中午开支部大会&#xff0c;下午学院职工会议&#xff0c;晚上去东联蛇餐馆吃蛇肉&#xff0c;回来后参加体验英语月闭幕式及英语合唱表演决赛。这中间我还出去给我的论文小组快了一个讨论会。昨天共开了三个会&#xff0c;真是忙得天昏地暗&#xff0…

NoSQL系列:选择合适的数据库

NoSQL系列&#xff1a;选择合适的数据库 为什么使用NoSQL数据库&#xff1f; 阻抗失衡 关系模型和内存中的数据结构不匹配 采用更为方便的数据交互方式提升开发效率 待处理的数据量很大 数据量超过关系型数据库的承载能力 大集群的出现 在成本方面&#xff0c;集群中应用关系数…

mysql历史日志文件_MySQL 历史 binlog 日志处理

MySQL 历史 binlog 日志处理一、问题的引出MySQL binlog 如果不清理会占用服务器的空间,那么怎么处理binlog日志呢二、解决办法1、物理删除df -Th 查看磁盘空间➜ bobbob-pc ~ df -Th文件系统 类型 容量 已用 可用 已用% 挂载点udev devtmpfs 7.8G 0 7.8G 0% /devtmpfs tmpfs 1…

史上最全搞怪WC标志(组图)--设计者太有才了。

转载于:https://www.cnblogs.com/onlyzq/archive/2007/12/22/1010318.html

1 vmware 如何联网,以及行命令令初步

VMware安装Linux&#xff08;我安装的是ubuntu&#xff09;&#xff0c;没法上网&#xff0c;上网教程见&#xff1a;https://blog.csdn.net/qq_28090573/article/details/78730552 安装完成Linux&#xff0c;进入系统&#xff0c;显示的是图形界面&#xff0c;但是学习Linux&a…

mysql几个timeout参数_MySQL中 timeout相关参数解析

前言&#xff1a;MySQL中有两个关于连接超时的配置项。他们之间在某些条件下会互相继承&#xff0c;那究竟这两个参数会在什么情况下起作用呢&#xff1f;本文将会通过一些测试实例来证明总结两者的相互关系。参数介绍&#xff1a;The number of seconds the server waits for …

XML操作类

publicclassXmlControl:Object { protectedstringstrXmlFile; protectedXmlDocument objXmlDoc newXmlDocument(); publicXmlControl(stringXmlFile, Boolean bOverWrite, stringsRoot) { try{ //如果覆盖模式&#xff…

shell脚本中if的相关参数

转自&#xff1a;http://blog.csdn.net/aaaaatiger/article/details/1713611[ -a FILE ] 如果 FILE 存在则为真。 [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。 [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。 [ -d FILE ] 如果 FILE 存在且是一个…