PSENet原理与代码解析
目录
Pipeline
Label Generation
Loss
PSE算法
论文 https://arxiv.org/abs/1806.02559
官方源码 GitHub - whai362/PSENet: Official Pytorch implementations of PSENet.
对形状鲁棒的文本检测存在两个挑战:
- 大多数现有的基于bounding box的检测方法不适用于对任意形状的文本(如弯曲文本)的检测
- 大多数现有的基于像素分割的检测方法可能无法将挨得非常近的文本区分开
为了解决这两个问题,作者提出了Pogressive Scale Expansion Network(PSENet)。PSENet是一个基于像素分割的检测方法,对于每个文本实例网络输出多个预测结果,每个预测结果对应的ground truth是将完整的文本标注区域按不同的比例缩放得到的多个“核”。然后通过PSE算法将网络输出的结果从小到大扩充得到最终预测结果。即使对于挨得很近的文本实例,将他们缩放后得到的核之间距离也足够大,因次可以很好地将挨得近的文本实例区分开,同时因为是基于像素分割的网络,对于任意形状的文本检测效果很鲁棒。
如上图,图(a)是原始图像。图(b)是基于bounding box检测方法的检测结果,因为检测框无法很好地拟合弯曲文本,导致某一文本实例的检测结果会覆盖其它文本实例。图(c)是传统基于像素分割的检测结果,因为前三行挨得太近导致网络将三个文本实例检测成一个。图(d)是PSENet也正是我们期望的检测结果。
Pipeline
1. 左边的蓝色部分为backbone,论文中是ResNet50,从下到上分别为ResNet50的conv_2x、conv_3x、conv_4x、conv_5x的输出C2、C3、C4、C5。原始输入为640*640*3,C2到C5的shape分别为160*160*256、80*80*512、40*40*1024、20*20*2048。
2. 中间的橘色部分作者借鉴的FPN,以第一个节点为例
20*20*2048的C5经过1*1*256的Conv、BN、ReLU得到20*20*256的P5
40*40*1024的C4经过1*1*256的Conv、BN、ReLU得到40*40*256的C4
P5经过upsample后与C4进行add得到40*40*256的中间结果
然后经过3*3*256的Conv、BN、ReLU得到40*40*256的P4
最终P2~P5的shape分别为160*160*256、80*80*256、40*40*256、20*20*256
3. P5、P4、P3分别upsample成P2的大小,然后concatenate得到160*160*1024的fusion feature即图中的F
4. 然后经过3*3*256的Conv、BN、ReLU、1*1*num_class(论文中num_class=6,包含1个完整的文本标注)得到7*160*160的特征图
5. 最后以stride=4,upsample成输入大小得到最终结果。模型的输入shape为(batch_size,3,640,640),输出shape为(batch_size,7,640,640)
Label Generation
图(a)(b)中的蓝色框为文本的原始也是完整的标注信息,对应于最大的segmentation label mask。通过将原始框向内缩放个像素得到对应的。将转化成0/1二值图即得到了对应不同预测kernel的ground truth。
的计算公式如下
其中是原始标注框,Area和Perimeter分别是面积和周长,的计算公式如下
其中m是最终缩放比例,n是kernel个数,论文中取m=0.5,n=6。i的取值范围为[1,n],是最小的kenel,是最大的kernel。
注意这里官方代码和论文有出入,代码中m=0.4, n=7,且计算的时候最后是乘以n而不是n-i。但只是生成的gt顺序相反,这里是最小的kernel,是最大,代码相反,并不影响训练。
Loss
和分别代表完整的文本实例的loss和缩放的文本实例的loss,是比例系数,论文中取0.7
其中和分别对应网络输出和对应的ground truth 中(x,y)处的值
因为图片中会有许多和文字笔画比较像的物体比如栅栏、格子图案等,因此对使用在线困难样本挖掘来更好的区分文本和这些相似的非文本。专注于区分文本和非文本。
M是采用了Online Hard Example Mining后得到的mask
def ohem_single(score, gt_text, training_mask):pos_num = int(np.sum(gt_text > 0.5)) - int(np.sum((gt_text > 0.5) & (training_mask <= 0.5)))# 去掉###的gt (training_mask在标签为###的位置值为0,其它位置为1)neg_num = int(np.sum(gt_text <= 0.5))neg_num = int(min(pos_num * 3, neg_num))neg_score = score[gt_text <= 0.5]# 模型预测结果图score在gt为背景的部分得分最大的neg_num个像素作为负样本neg_score_sorted = np.sort(-neg_score) # 从小到大threshold = -neg_score_sorted[neg_num - 1]selected_mask = ((score >= threshold) | (gt_text > 0.5)) & (training_mask > 0.5)selected_mask = selected_mask.reshape(1, selected_mask.shape[0], selected_mask.shape[1]).astype('float32')return selected_mask
缩放的文本实例的计算公式如下
因为shrunk kernels是被完整的文本实例包围的,因此在计算时忽略网络输出中非文本的区域,即这里的,来avoid a certain redundancy。
注意代码中计算公式如下,但是最终结果和论文中是一样的
PSE算法
def pse(kernals, min_area):kernal_num = len(kernals) pred = np.zeros(kernals[0].shape, dtype='int32')label_num, label = cv2.connectedComponents(kernals[kernal_num - 1], connectivity=4)# 找网络输出最小kernel中的连通域。# 这里的label_num是连通域个数(包含背景)。label是和输入大小相同的图,若一共5个联通域,则label的背景部分值为0,5个连通域的值分别为1~5for label_idx in range(1, label_num):if np.sum(label == label_idx) < min_area:label[label == label_idx] = 0queue = Queue.Queue(maxsize=0) # 先进先出next_queue = Queue.Queue(maxsize=0)points = np.array(np.where(label > 0)).transpose((1, 0)) # (10234, 2)所有连通域内的点for point_idx in range(points.shape[0]):x, y = points[point_idx, 0], points[point_idx, 1] # 注意这里x是第一维对应的是图像的高l = label[x, y]queue.put((x, y, l))pred[x, y] = ldx = [-1, 1, 0, 0]dy = [0, 0, -1, 1]for kernal_idx in range(kernal_num - 2, -1, -1):kernal = kernals[kernal_idx].copy() # 从上一个kernel即queue里存的值往当前kernel扩充while not queue.empty():(x, y, l) = queue.get()is_edge = Truefor j in range(4):tmpx = x + dx[j]tmpy = y + dy[j]if tmpx < 0 or tmpx >= kernal.shape[0] or tmpy < 0 or tmpy >= kernal.shape[1]:continueif kernal[tmpx, tmpy] == 0 or pred[tmpx, tmpy] > 0: # 当前kernel这个点像素为0或者已经扩充过了continuequeue.put((tmpx, tmpy, l))pred[tmpx, tmpy] = lis_edge = Falseif is_edge:next_queue.put((x, y, l))queue, next_queue = next_queue, queue# next_queue里存的是is_edge的像素点,queue是空的。然后下一轮只从is_edge即最外层轮廓开始expandreturn pred
PSENet原理与代码解析相关推荐
- 视觉SLAM开源算法ORB-SLAM3 原理与代码解析
来源:深蓝学院,文稿整理者:何常鑫,审核&修改:刘国庆 本文总结于上交感知与导航研究所科研助理--刘国庆关于[视觉SLAM开源算法ORB-SLAM3 原理与代码解析]的公开课. ORB-SLA ...
- Tensorflow2.0---SSD网络原理及代码解析(二)-锚点框的生成
Tensorflow2.0-SSD网络原理及代码解析(二)-锚点框的生成 分析完SSD网络的原理之后,一起来看看代码吧~ 代码转载于:https://github.com/bubbliiiing/ss ...
- ICCV2017跟踪算法BACF原理及代码解析
文章和代码下载地址: Galoogahi H K, Fagg A, Lucey S. Learning Background-Aware Correlation Filters for Visual ...
- DBNet++(TPAMI) 原理与代码解析
paper:Real-Time Scene Text Detection with Differentiable Binarization and Adaptive Scale Fusion code ...
- G-GhostNet(IJCV 2022)原理与代码解析
paper:GhostNets on Heterogeneous Devices via Cheap Operations code:https://github.com/huawei-noah/Ef ...
- YOLOv3原理及代码解析
博主完整翻译了YOLOV1和YOLOV3的论文:请移步查看: YOLOV1:https://blog.csdn.net/taifengzikai/article/details/81988891 YO ...
- 【资源】CenterNet原理与代码解析
<CenterNet原理与代码解析>是首发于GiantPandaCV公众号的电子书教程,由pprp总结并整理CenterNet相关解析,这本电子书是基于非官方的CenterNet实现,ht ...
- TPAMI2015跟踪算法KCF原理及代码解析
文章和代码下载地址: http://www.robots.ox.ac.uk/~joao/circulant/ 一.基础公式的由来 相关滤波跟踪器可以表示为最小化的岭回归问题: 表示期望相应,表示正则系 ...
- ViBe算法原理和代码解析
ViBe - a powerful technique for background detection and subtraction in video sequences 算法官网:http:// ...
- ORB-SLAM / ORB-SLAM2原理解读+代码解析(汇总了资料,方便大家学习)
注释:本文非原创,初学搜集了很多资料附上链接,方便初学者学习,避免盲目搜索浪费时间. 目录 官方代码链接 代码框架思维导图 参考解读 参考链接- -一步步带你看懂orbslam2源码 ORB-SLAM ...
最新文章
- linux c 函数专挑,Linux C wait函数
- JSP学习笔记(五):日期处理、页面重定向、点击量统计、自动刷新和发送邮件...
- php upload ctf,强网杯CTF防御赛ez_upload Writeup
- pyspark dataframe数据连接(join)、转化为pandas dataframe、基于多个字段删除冗余数据
- vim8支持的linux版本,Vim 8.0 版本安装方法及添加Python支持
- Java8的十大新特性
- IDEA 中 30 秒生成 Spring Cloud Alibaba 工程
- oracle01507报错,oracle报错ORA-01507
- SpringMVC介绍之Validation
- 我最喜欢的Java高级开发人员书籍
- mysql镜像远程连接_docker 创建mysql镜像,并成功进行远程连接
- 【原】母版页、皮肤、导航 那点事 Master Pages Themes and Navigation Controls FAQ
- 新一代CTR预测服务的GPU优化实践
- WBS和TASK的区别?
- Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
- 捡到的文物应该归谁最好
- module ‘eli5‘ has no attribute ‘show_weights‘
- API管理神器:Apifox
- 腾讯云 直播 OBS 在线推流
- PSI 项目经理 PMP 计算题公式人话版解释
热门文章
- PyTorch中的pack_padded_sequence和pad_packed_sequence
- 小程序源码:图片秒加水印制作生成-多玩法安装简单
- 题解 P2184 【贪婪大陆】
- 程序员表白技巧:程序员木讷? 我反手就是一串代码
- 来自清华学子的一个自述---在树洞里
- 怎么判断苹果开发者账号是否认证了
- 网络安全守护神(SOC)
- 综述:环境中的噬菌体宿主互作
- AlertDialog点击确定必定会dismiss问题
- relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol may bind externally can not be used 【ARM64平台编译】