[论文笔记]Arbitrary-Oriented Scene Text Detection via Rotation Proposals

本文主要是介绍[论文笔记]Arbitrary-Oriented Scene Text Detection via Rotation Proposals,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Arbitrary-Oriented Scene Text Detection via Rotation Proposals

论文地址:https://arxiv.org/abs/1703.01086

github地址:https://github.com/mjq11302010044/RRPN

该论文是基于faster-rcnn框架,在场景文字识别领域的应用。


创新点:生成带文字角度信息的倾斜的proposal

1.RRPN(Rotation Region Proposal Networks):生成带角度信息的anchor,从而生成任意方向的proposals.

2.RRoI(The Rotation Region-of-Interest) pooling layer:将任意方向的proposals映射到feature map上,再进行max pooling.


RRPN部分:

数据预处理:

groud truth of a text region:(x,y,h,w,θ)

其中,x,y为bounding box的几何中心;h为bounding box的短边,w为bounding box的长边;θ为bounding box长边旋转的角度,范围为


Anchors:


1.angle:-pi/6, 0, pi/6, pi/3, pi/2 以及2pi/3

规定bounding box的旋转范围为[3pi/4,-pi/4),而anchor的旋转角度包括:-pi/6, 0, pi/6, pi/3, pi/2 以及2pi/3

要求每个anchor对应的target的旋转角度和anchor本身的旋转角度差不能超过pi/12,这称为fit domain。

因此,anchor对应的target的旋转角度范围如下:

anchor角度target旋转角度范围
-pi/6[-pi/4,-pi/12)
0[-pi/12,pi/12)
pi/6[pi/12,pi/4)
pi/3[pi/4,5pi/12)
pi/2[5pi/12,7pi/12)
2pi/3[7pi/12,3pi/4)


可以看到,anchor与对应的target的角度差不超过pi/12.

2.aspect ration: 1:2, 1:5, 1:8

3.scale:8,16,32

对于feature map上面的每一点,生成的anchors的数量为6*3*3=54个。

除了增加了角度信息,生成anchor的方式与faster-rcnn类似。
在过滤的时候使用了 Scale Jittering策略。
步骤:
1.给图像增加大小为原边长0.25倍的border-padding。
2.利用给定的anchor(x,y,w,h,θ)信息,生成anchor的四个顶点坐标。
3.判断四个顶点坐标是否在新边界内。


IoU:


思想:先算出两个矩阵边的交点,然后生成一个多变形,最后将多边形分割成三角形进行计算。
伪代码如下:



RRoI部分:
RRoI Pooling算法:
1)将每一个proposal分成7×7的sub regions。
2)对每一个sub region的四个点,进行affine Transformation(仿射变换),得到对应的平行四边形。
3)对feature map中的平行四边形进行max pooling。
伪代码:


Affine Transformation(仿射变换):

参考:https://www.cnblogs.com/ghj1976/p/5199086.html,思路很棒,但是其中列举的部分矩阵有错误,已在本文订正。

1)概念

仿射变换,就是允许图形任意倾斜,而且允许图形在两个方向上任意伸缩的变换。其可以保持原来的线共点,点共线的关系不变,保持原来相互平行的线仍然平行,保持原来的中点仍然是中点,保持原来在一直线上几段线段之间的比例关系不变。

但是,仿射变换不能保持原来的线段长度不变,也不能保持原来的夹角角度不变。


仿射变换可以用下面公式表示:


其中,(tx,ty)表示平移量,而参数ai则反映了图像旋转,缩放等变化。将参数tx,ty,ai(i=1~4)计算出,即可得到两幅图形的坐标变换关系。

2)RRPN中用到的变换举例:

a)平移变换(Translation)

将每一点移动到(x+tx, y+ty),变换矩阵为:


平移变换不会产生形变。

效果:


b)旋转变换(Rotation)

目标图形围绕原点顺时针旋转θ弧度,变换矩阵为:


效果:


c)  缩放变换(scale)

将每一点的横坐标放大(缩小)至sx倍,纵坐标放大(缩小)至sy倍,变换矩阵为:


效果:


d)组合

目标图形以(x,y)为轴心顺时针旋转θ弧度,变换矩阵为:


相当于两次平移变换与一次原点旋转变换的组合,也就是先移动到中心节点,然后旋转,然后再移动回去。



平移与旋转的变换效果如下:



RRoI Pooling 实现

相信有了前面affine Transformation(仿射变换)的铺垫,RRoI Pooling的关键代码相对而言可以较为容易的看懂。

/home/crediks/Downloads/RRPN/caffe-fast-rcnn/src/caffe/layers/roi_pooling_layer.cpp:

void RotateROIPoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) {const Dtype* bottom_data = bottom[0]->cpu_data();const Dtype* bottom_rois = bottom[1]->cpu_data();const Dtype* image_info = bottom[2]->cpu_data();// Number of ROIsint num_rois = bottom[1]->num();int batch_size = bottom[0]->num();int top_count = top[0]->count();Dtype* top_data = top[0]->mutable_cpu_data();caffe_set(top_count, Dtype(-FLT_MAX), top_data);int* argmax_data = max_idx_.mutable_cpu_data();caffe_set(top_count, -1, argmax_data);int imageWidth = int(image_info[1]*spatial_scale_+0.5);int imageHeight = int(image_info[0]*spatial_scale_+0.5);// For each ROI R = [batch_index Cx Cy height width angle]: max pool over R for (int n = 0; n < num_rois; ++n) {// Pointsint roi_batch_ind = bottom_rois[0];CHECK_GE(roi_batch_ind, 0);CHECK_LT(roi_batch_ind, batch_size);Dtype cx = bottom_rois[1];Dtype cy = bottom_rois[2];Dtype h = bottom_rois[3];Dtype w = bottom_rois[4];Dtype angle = bottom_rois[5]/180.0*3.1415926535;//TransformPrepareDtype dx = -pooled_width_/2.0;Dtype dy = -pooled_height_/2.0;//每一个sub region的大小Dtype Sx = w*spatial_scale_/pooled_width_;Dtype Sy = h*spatial_scale_/pooled_height_;Dtype Alpha = cos(angle);Dtype Beta = sin(angle);Dtype Dx = cx*spatial_scale_;Dtype Dy = cy*spatial_scale_;Dtype M[2][3]; M[0][0] = Alpha*Sx;M[0][1] = Beta*Sy;M[0][2] = Alpha*Sx*dx+Beta*Sy*dy+Dx;M[1][0] = -Beta*Sx;M[1][1] = Alpha*Sy;M[1][2] = -Beta*Sx*dx+Alpha*Sy*dy+Dy;/*std::cout<<M[0][0]<<std::endl;std::cout<<M[0][1]<<std::endl;std::cout<<M[0][2]<<std::endl;std::cout<<M[1][0]<<std::endl;std::cout<<M[1][1]<<std::endl;std::cout<<M[1][2]<<std::endl;    
*/const Dtype* batch_data = bottom_data + bottom[0]->offset(roi_batch_ind);for (int c = 0; c < channels_; ++c) {for (int ph = 0; ph < pooled_height_; ++ph) {for (int pw = 0; pw < pooled_width_; ++pw) {const int pool_index = ph * pooled_width_ + pw;Dtype P[8];P[0] = M[0][0]*pw+M[0][1]*ph+M[0][2];P[1] = M[1][0]*pw+M[1][1]*ph+M[1][2];P[2] = M[0][0]*pw+M[0][1]*(ph+1)+M[0][2];P[3] = M[1][0]*pw+M[1][1]*(ph+1)+M[1][2];P[4] = M[0][0]*(pw+1)+M[0][1]*ph+M[0][2];P[5] = M[1][0]*(pw+1)+M[1][1]*ph+M[1][2];P[6] = M[0][0]*(pw+1)+M[0][1]*(ph+1)+M[0][2];P[7] = M[1][0]*(pw+1)+M[1][1]*(ph+1)+M[1][2];std::cout<<imageWidth<<imageHeight<<std::endl;int leftMost = int(max(round(min(min(P[0],P[2]),min(P[4],P[6]))) ,0.0));int rightMost= int(min(round(max(max(P[0],P[2]),max(P[4],P[6]))),imageWidth-1.0));int topMost= int(max(round(min(min(P[1],P[3]),min(P[5],P[7]))),0.0));int bottomMost= int(min(round(max(max(P[1],P[3]),max(P[5],P[7]))),imageHeight-1.0));//bool is_empty = (rightMost<= leftMost) || (bottomMost <= topMost);         //std::cout<<leftMost<<rightMost<<topMost<<bottomMost<<std::endl;Dtype AB[2];AB[0] = P[2] - P[0];AB[1] = P[3] - P[1];	Dtype ABAB = AB[0]*AB[0] +AB[1]*AB[1];Dtype AC[2];AC[0] = P[4] - P[0];AC[1] = P[5] - P[1];Dtype ACAC = AC[0]*AC[0] + AC[1]*AC[1];top_data[pool_index] = 0;argmax_data[pool_index] = -1;for (int h = topMost; h < bottomMost+1; ++h) {for (int w = leftMost; w < rightMost+1; ++w) {Dtype AP[2];AP[0] = w - P[0];AP[1] = h - P[1];Dtype ABAP = AB[0]*AP[0] +AB[1]*AP[1];Dtype ACAP = AC[0]*AP[0] + AC[1]*AP[1];if(ABAB>ABAP&&ABAP>=0&&ACAC>ACAP&&ACAP>=0){const int index = h * width_ + w;if (batch_data[index] > top_data[pool_index]) {top_data[pool_index] = batch_data[index];argmax_data[pool_index] = index;}}}}}}// Increment all data pointers by one channelbatch_data += bottom[0]->offset(0, 1);top_data += top[0]->offset(0, 1);argmax_data += max_idx_.offset(0, 1);}// Increment ROI data pointerbottom_rois += bottom[1]->offset(1);}
}

1.矩阵M定义了Affine Transformation的变换矩阵。包含了缩放,旋转,平移操作。

2.通过缩放,旋转,平移,找到sub region对应的平行四边形在feature map上的坐标。也就是p[0]~p[7],示意图如下:


3.由于θ的大小不一定,所以p[0],p[2],p[4],p[6]均有可能为最左边的坐标。最右,最上和最下同理。通过比较坐标的位置,找到最左,最右,最上和最下的坐标。

4.过滤掉无效位置(if(ABAB>ABAP&&ABAP>=0&&ACAC>ACAP&&ACAP>=0)...)

5.最后进行max pooling.

实验说明:

ICDAR2015数据集:利用数据集中给定的四个顶点,生成倾斜的Bounding box;

ICDAR2013数据集:生成水平方向的Bounding box。

调参技巧:前20万次迭代lr为0.0001

后10万次迭代lr为0.0005

过滤:由于生成的anchors的数量为原来的6倍,因此将超出边框的anchors进行过滤。

运行部分:

bug解决方案:


Segmentation fault,错误解决方案:

./lib/rotation/data_extractor.py:

1.将import cv2的顺序提前,也就是将import文件的顺序改为:

import cv2
import numpy as np
import os
from xml.dom.minidom import parse
import xml.dom.minidom
from PIL import Image
import pickle

./tools/train_net.py:


2.将from rotation.data_extractor import get_rroidb的顺序提前,也就是将import文件的顺序改为:

from rotation.data_extractor import get_rroidb
import _init_paths
#from fast_rcnn.train import get_training_roidb, train_net #D
from rotation.rt_train import get_training_roidb, train_net
from fast_rcnn.config import cfg, cfg_from_file, cfg_from_list, get_output_dir
from datasets.factory import get_imdb
from rotation.data_extractor import get_rroidb
import datasets.imdb
import caffe
import argparse
import pprint
import numpy as np
import sys


这篇关于[论文笔记]Arbitrary-Oriented Scene Text Detection via Rotation Proposals的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128620

相关文章

AI hospital 论文Idea

一、Benchmarking Large Language Models on Communicative Medical Coaching: A Dataset and a Novel System论文地址含代码 大多数现有模型和工具主要迎合以患者为中心的服务。这项工作深入探讨了LLMs在提高医疗专业人员的沟通能力。目标是构建一个模拟实践环境,人类医生(即医学学习者)可以在其中与患者代理进行医学

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文翻译:arxiv-2024 Benchmark Data Contamination of Large Language Models: A Survey

Benchmark Data Contamination of Large Language Models: A Survey https://arxiv.org/abs/2406.04244 大规模语言模型的基准数据污染:一项综述 文章目录 大规模语言模型的基准数据污染:一项综述摘要1 引言 摘要 大规模语言模型(LLMs),如GPT-4、Claude-3和Gemini的快

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi