AdvanceEast源码理解
文章思路
大神的github和个人网站已经对此进行了说明,这里不再赘述。。。
源码理解
一. 标签点形式
- 给四个点排列顺序制定规则
'''
按顺序排列四个点,逆时针旋转,且第一个点为左上角点(刚开始选择最左边的点,
如果最后计算的第二个点的Y比第一个点大,那就让最后一个点做为第一个点,其他点依次右移)
1.以最小的X坐标为起点(起名为A)
2.其他三个点和第一个点(A)连线形成夹角,取中间的点为第三个点(起名C)
3.以AC为连线,在AC上方为D,下方为B
4.最后比较AC和BD的斜率,AC>BD ===> 顺序调整为DABC AC<BD ===> 维持ABCD
5.感觉第四步没啥意义,只要是顺序就好了,没必要那么苛刻。。。。
'''
- 下面给出一些例子
- 注意长边的位置
针对上面两幅图,第一张的long_edge=0,2
,第二张的long_edge=1,3
二. 标签切边
- 以最短边的0.3进行缩放当做内部点
- 以最短边的0.6作为头尾点
注意:这里头尾都是针对最长边上的操作
注意:头和尾是按照标签点的顺序进行的,排在前面为头,排在后面为尾
三. loss计算
这部分比较简单,建议由需要的读者直接读取一个data
进行debug即可:
#input : 1*w*h*3
#label : 1*160*160*7(batch,w,h,type)
def quad_loss(y_true, y_pred):
# loss for inside_score
logits = y_pred[:, :, :, :1]
labels = y_true[:, :, :, :1]
# balance positive and negative samples in an image
beta = 1 - tf.reduce_mean(labels)
# first apply sigmoid activation
predicts = tf.nn.sigmoid(logits)
# log +epsilon for stable cal
inside_score_loss = tf.reduce_mean(
-1 * (beta * labels * tf.log(predicts + cfg.epsilon) +
(1 - beta) * (1 - labels) * tf.log(1 - predicts + cfg.epsilon)))
inside_score_loss *= cfg.lambda_inside_score_loss
# loss for side_vertex_code
vertex_logits = y_pred[:, :, :, 1:3]
vertex_labels = y_true[:, :, :, 1:3]
vertex_beta = 1 - (tf.reduce_mean(y_true[:, :, :, 1:2])
/ (tf.reduce_mean(labels) + cfg.epsilon))
vertex_predicts = tf.nn.sigmoid(vertex_logits)
pos = -1 * vertex_beta * vertex_labels * tf.log(vertex_predicts +
cfg.epsilon)
neg = -1 * (1 - vertex_beta) * (1 - vertex_labels) * tf.log(
1 - vertex_predicts + cfg.epsilon)
positive_weights = tf.cast(tf.equal(y_true[:, :, :, 0], 1), tf.float32)
side_vertex_code_loss = \
tf.reduce_sum(tf.reduce_sum(pos + neg, axis=-1) * positive_weights) / (
tf.reduce_sum(positive_weights) + cfg.epsilon)
side_vertex_code_loss *= cfg.lambda_side_vertex_code_loss
# loss for side_vertex_coord delta
g_hat = y_pred[:, :, :, 3:]
g_true = y_true[:, :, :, 3:]
vertex_weights = tf.cast(tf.equal(y_true[:, :, :, 1], 1), tf.float32)
pixel_wise_smooth_l1norm = smooth_l1_loss(g_hat, g_true, vertex_weights)
side_vertex_coord_loss = tf.reduce_sum(pixel_wise_smooth_l1norm) / (
tf.reduce_sum(vertex_weights) + cfg.epsilon)
side_vertex_coord_loss *= cfg.lambda_side_vertex_coord_loss
return inside_score_loss + side_vertex_code_loss + side_vertex_coord_loss
def smooth_l1_loss(prediction_tensor, target_tensor, weights):
n_q = tf.reshape(quad_norm(target_tensor), tf.shape(weights))
diff = prediction_tensor - target_tensor
abs_diff = tf.abs(diff)
abs_diff_lt_1 = tf.less(abs_diff, 1)
pixel_wise_smooth_l1norm = (tf.reduce_sum(
tf.where(abs_diff_lt_1, 0.5 * tf.square(abs_diff), abs_diff - 0.5),
axis=-1) / n_q) * weights
return pixel_wise_smooth_l1norm
def quad_norm(g_true):
shape = tf.shape(g_true)
delta_xy_matrix = tf.reshape(g_true, [-1, 2, 2])
diff = delta_xy_matrix[:, 0:1, :] - delta_xy_matrix[:, 1:2, :]
square = tf.square(diff)
distance = tf.sqrt(tf.reduce_sum(square, axis=-1))
distance *= 4.0
distance += cfg.epsilon
return tf.reshape(distance, shape[:-1])
if __name__ == '__main__':
x, y = data_generator.gen(1)
loss_t = quad_loss(y,y)
四. NMS
这部分没仔细看,传统的NMS和LNMS都比较简单,大概看一下就好了
这里主要是说明一下几个参数:
pixel_threshold = 0.9 #内部点阈值(目标点概率)
side_vertex_pixel_threshold = 0.9 #内部头尾点的阈值
##头尾点取值范围,head->[0,trunc_threshold] tail->[1-trunc_threshold,1],变大之后检测能力变强
trunc_threshold = 0.1
最后说明
其实这个项目的思路很简单,看一下就明白,但是具体实现还是有点棘手,难点在于标签的制作
边界点负责回归边界,这个边界如何确定?如何确定头和尾?
具体代码的注释写在里面了,还有很多小细节看笔者注释即可
下载地址
AdvanceEast源码理解的更多相关文章
- Caffe源码理解2:SyncedMemory CPU和GPU间的数据同步
目录 写在前面 成员变量的含义及作用 构造与析构 内存同步管理 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 在Caffe源码理解1中介绍了Blob类,其中的数据成 ...
- 基于SpringBoot的Environment源码理解实现分散配置
前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Envi ...
- jedis的源码理解-基础篇
[jedis的源码理解-基础篇][http://my.oschina.net/u/944165/blog/127998] (关注实现关键功能的类) 基于jedis 2.2.0-SNAPSHOT ...
- VUEJS2.0源码理解--优
VUEJS2.0源码理解 http://jiongks.name/blog/vue-code-review/#pingback-112428
- Pytorch学习之源码理解:pytorch/examples/mnists
Pytorch学习之源码理解:pytorch/examples/mnists from __future__ import print_function import argparse import ...
- .NET Core 3.0之深入源码理解Startup的注册及运行
原文:.NET Core 3.0之深入源码理解Startup的注册及运行 写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程 ...
- 深入源码理解Spring整合MyBatis原理
写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...
- HashMap源码理解一下?
HashMap 是一个散列桶(本质是数组+链表),散列桶就是数据结构里面的散列表,每个数组元素是一个Node节点,该节点又链接着多个节点形成一个链表,故一个数组元素 = 一个链表,利用了数组线性查找和 ...
- JS魔法堂:剖析源码理解Promises/A规范
一.前言 Promises/A是由CommonJS组织制定的异步模式编程规范,有不少库已根据该规范及后来经改进的Promises/A+规范提供了实现 如Q, Bluebird, when, rsvp. ...
随机推荐
- Lucene入门+实现
Lucene简介详情见:(https://blog.csdn.net/Regan_Hoo/article/details/78802897) lucene实现原理 其实网上很多资料表明了,lucene ...
- 多线程面试题之【三线程按顺序交替打印ABC的方法】
建立三个线程,线程名字分别为:A.B.C,要求三个线程分别打印自己的线程名字,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印.打印10轮,打印完毕控制台输出字符串:&q ...
- C#ModBus Tcp 报文解析
上一篇博客已经完成 C#ModBus Tcp Master的实现 本篇主要对不同的功能码所发出的报文进行解析(包括请求报文及响应报文) 读操作 功能码 0x01 读一组线圈 读取站号为1 从地址12开 ...
- jquery input file 多图上传,单张删除,查看
<div class="form-group"> <label for="imgs" class="col-md-3 col-sm- ...
- iOS滤镜功能
一.iOS自带滤镜 1.CoreImage 使用苹果自带的CoreImage框架对图片进行处理,用CoreImage框架里的CIFilter对图片进行滤镜处理, 首先我们应该了解下CoreImage框 ...
- reinterpret
reinterpret意为“重新解释” reinterpret_cast是C++中与C风格类型转换最接近的类型转换运算符.它让程序员能够将一种对象类型转换为另一种,不管它们是否相关. reinterp ...
- SQLSEVER 同台服务器下不同表 触发器实现数据实时同步
触发器的使用: 1.首先建立两个相同结构的表,两个表明的列的名称不同. student_01 字段 name ; 字段 age ; 字段 class ; student_02 字段 ...
- Set的交集、差集踩坑记录
项目中我用到了Set的retainAll和removeAll两个方法取差集和交集. 用法网上都有,我也不展示了. 但是因为我是急着用,直接就照着写了,没想到出大问题了. 因为我的set是一个map的k ...
- JavaScript函数封装调用
举个列子:我们在写前端页面,经常会使用到Jquery文本框内容,来判断一下输入值是否符合,常见的写法: <script> function test(){ $("#ID" ...
- Vue 中的Vue Router一级路由,二级路由,三级路由以及跳转
今天编写了一下Vue中的路由 先用命令行新建一个空的项目,并且我知道要用路由,就下载了路由的相关依赖 vue init webpack demo5 完毕之后进入所在的项目 cd demo5 之后用vs ...