1. Network Design
只包含两个阶段:全卷积网络(FCN)和NMS,其中FCN网络包括三个部分,特征提取+特征合并分支+输出层部分。由FCN直接生成单词或者文本行的逐像素预测,生成旋转的矩形或者四边形的候选区域,形成文本区域,最后由NMS处理
特征提取部分
想法来自U-shape的结合不同级别feature-map,设计四个层次的特征图,实验采用的VGG的各个feature-map的通道数和大小如图
特征合并分支
自底向上合并,每次合并沿通道concat,合并前需要将上一层的feature-map double size,然后concat当前feature-map,最后得到x=[1,32,64,64]
输出层部分(RBOX geometry map)
- x 经过一个卷积将32通道减少到1通道[1,1,64,64],这是score_map,存的是[0,1]像素分值图,表示这张图片上是文本区域的概率
- x经过一个卷积将32通道映射到4通道[1,4,64,64],并且乘上512,这是放大到crop的特征图大小(512*512),4通道表示上,下,左,右四个方向
- x 经过一个卷积将32通道减少到1通道[1,1,64,64],乘上[-π/2,π/2],表示角度
- 最后loc和angle进行concat成geo五通道[1,5,64,64],4通道表示每一个像素到矩形的上,下,左,右边界的距离,以及1通道旋转角度θ
2. Laebl Generation
2.1 缩小区域
对于每个顶点,计算相邻的两条边的长度,记r为短的一条,对于某一条边长度为len,它的两端点缩进0.3* r1 / len 与 0.3 * r2 / len,如图,当r1与r2比较,r2较短时,左移的少
点的调整可以设计成向量的形式
2.2 寻找最小外包矩形
这时整个流程里最重要的一步,对于可能的黑色区域部分,从轴从角度-π/2到π/2旋转,转动过程中寻找最小外包矩形,整个过程走完后找到最小的前10个外包矩形,计算误差,选取最小误差假定为图中绿色部分,记录此时θ为45°,最后需要更新到框边界的4个距离(上下左右),首先为了方便计算,将此多边形区域旋转45°到水平轴x轴,方便计算垂直和水平距离,然后相应的让整个坐标系也旋转45°,计算整张图片相对于四条线的距离,由于多边形内部标定为1,计算距离后乘上mask后会让多边形以外部分也也记为0,最后只有红色区域内是1,也就是要拿去训练的
5. Dice coefficient
计算 Dice Loss,因为普通的交叉熵无法解决样本不均衡问题!!!传送门
def get_dice_loss(gt_score,pred_score):
inter=torch.sum(gt_score*pred_score)
union=torch.sum(gt_score)+torch.sum(pred_score)+1e-5
return 1.-(2*inter/union)
4. locality-aware NMS(LANMS)
在NMS之前,对于y坐标相邻很近的box先进行一次合并,然后再进行NMS解决时间复杂度O(n²)的问题
def weighted_merge(g,p):
#取g,p两个几何体的加权平均(权重根据对应的检测得分计算得到)
g[:8]=(g[8]*g[:8]+p[8]*p[:8])/(g[8]+p[8])
g[8]=(g[8]+p[8])
return g
def nms_locality(polys,thres=0.3):
'''
locality aware nms of EAST
:param polys:a (n,9) numpy array.first 8 coordinates,then prob score
:param thres:0.3
:return:boxes after nms
'''
S=[]
p=None
#按照第一列排序的,也就是按行枚举点,相邻的可能具有相同部分
for g in polys:
#此处如果不优化,就是O(n*n)时间复杂度,这里采用先合并
if p is not None and intersection(g,p)>thres:
p=weighted_merge(g,p)
else:
if p is not None:
S.append(p)
p=g
if p is not None:
S.append(p)
if len(S)==0:
return np.array([])
#[[9],[9]]
return standard_nms(np.array(S),thres)
网友评论