目录

原理介绍

Label Generation

Loss函数

后处理


论文 https://arxiv.org/abs/1911.08947

代码 https://github.com/WenmuZhou/DBNet.pytorch

官方解读 https://megvii.blog.csdn.net/article/details/103502283

原理介绍

基于分割的文本检测方法后处理方法通常都是(1)设定固定阈值将分割模型得到的概率图转化为二值图(2)通过一些启发式方法例如像素聚类得到文本实例。本文的创新之处在于将二值化操作嵌入到分割网络中进行联合训练优化,图像中每点的阈值通过网络学习得到,从而把前景像素和背景像素完全区分开。

概率图(probability map)和经二值化后的二值图(binary map)共享同一个监督,即文本实例shrink后的kernel,而阈值图的ground truth则是文本实例边界附近区域的像素距离边界的距离,文中说即使没有监督阈值图的输出也会强调边缘信息,如下面左边是无监督的阈值图输出,右边是以边缘信息为监督的阈值图,因此用边缘信息作为阈值图的监督有助于最终的结果。

标准的二值化公式如下,其中是概率图,是图中的像素坐标,是固定阈值,是输出的二值图

但是标准的二值化不可微,没法和分割网络一起训练优化,因此作者提出了可微分的二值化,公式如下,其中是阈值图,取50

从下图可以看出可微分二值化和标准二值化很相似,且可微分,因此可以和分割网络一起联合优化。

Label Generation

概率图的label和psenet一样,以shrink距离D后的kernel作为标签,具体可以参考psenet。阈值图是文本实例边缘向内shrink距离D到向外expand距离D这个区域内,计算每个像素点到文本边缘的距离作为gt值,距离越近值越大,官方实现中归一化到0.3~0.7之间。生成的标签如下所示,其中红线是文本原始边缘,蓝线是shrink后的边缘,绿线是expand后的边缘

生成阈值图ground truth的代码如下

class MakeBorderMap:def __init__(self, shrink_ratio=0.4, thresh_min=0.3, thresh_max=0.7):self.shrink_ratio = shrink_ratio  # 0.4self.thresh_min = thresh_min  # 0.3self.thresh_max = thresh_max  # 0.7def __call__(self, data: dict) -> dict:""":param data: {'img':,'text_polys':,'texts':,'ignore_tags':}"""im = data['img']text_polys = data['text_polys']ignore_tags = data['ignore_tags']canvas = np.zeros(im.shape[:2], dtype=np.float32)mask = np.zeros(im.shape[:2], dtype=np.float32)for i in range(len(text_polys)):if ignore_tags[i]:continueself.draw_border_map(text_polys[i], canvas, mask=mask)canvas = canvas * (self.thresh_max - self.thresh_min) + self.thresh_min  # 归一化到0.3到0.7之内data['threshold_map'] = canvasdata['threshold_mask'] = maskreturn datadef draw_border_map(self, polygon, canvas, mask):polygon = np.array(polygon)  # (4,2)assert polygon.ndim == 2assert polygon.shape[1] == 2polygon_shape = Polygon(polygon)if polygon_shape.area <= 0:returndistance = polygon_shape.area * (1 - np.power(self.shrink_ratio, 2)) / polygon_shape.lengthsubject = [tuple(l_) for l_ in polygon]padding = pyclipper.PyclipperOffset()padding.AddPath(subject, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)padded_polygon = np.array(padding.Execute(distance)[0])  # 往外扩# padding.Execute结果可能会出现负数cv2.fillPoly(mask, [padded_polygon.astype(np.int32)], 1.0)xmin = padded_polygon[:, 0].min()xmax = padded_polygon[:, 0].max()ymin = padded_polygon[:, 1].min()ymax = padded_polygon[:, 1].max()width = xmax - xmin + 1height = ymax - ymin + 1# 往外扩大之后的polygon的正的外接矩形polygon[:, 0] = polygon[:, 0] - xmin  # 原始的polygon坐标平移到这个正的矩形框内polygon[:, 1] = polygon[:, 1] - yminxs = np.broadcast_to(np.linspace(0, width - 1, num=width).reshape(1, width), (height, width))ys = np.broadcast_to(np.linspace(0, height - 1, num=height).reshape(height, 1), (height, width))# 以这个正的外接矩形左上角为原点,矩形区域内所有点的横坐标和纵坐标distance_map = np.zeros((polygon.shape[0], height, width), dtype=np.float32)for i in range(polygon.shape[0]):  # 4j = (i + 1) % polygon.shape[0]absolute_distance = self.distance(xs, ys, polygon[i], polygon[j])distance_map[i] = np.clip(absolute_distance / distance, 0, 1)  # 只考虑原始polygon向里外扩distance这个区域distance_map = distance_map.min(axis=0)# 这一步是限制polygon某条边附近distance区域内的点只取到这条边的距离,而不是到其它边的距离xmin_valid = min(max(0, xmin), canvas.shape[1] - 1)xmax_valid = min(max(0, xmax), canvas.shape[1] - 1)ymin_valid = min(max(0, ymin), canvas.shape[0] - 1)ymax_valid = min(max(0, ymax), canvas.shape[0] - 1)canvas[ymin_valid: ymax_valid + 1, xmin_valid: xmax_valid + 1] = np.fmax(  # Element-wise maximum of array elements1 - distance_map[ymin_valid - ymin: ymax_valid - ymax + height,xmin_valid - xmin: xmax_valid - xmax + width],canvas[ymin_valid: ymax_valid + 1, xmin_valid: xmax_valid + 1])# 距离原始polygon越近值越接近1,超出distance的值都为0@staticmethoddef distance(xs, ys, point_1, point_2):"""compute the distance from point to a lineys: coordinates in the first axisxs: coordinates in the second axispoint_1, point_2: (x, y), the end of the line"""# height, width = xs.shape[:2]square_distance_1 = np.square(xs - point_1[0]) + np.square(ys - point_1[1])square_distance_2 = np.square(xs - point_2[0]) + np.square(ys - point_2[1])square_distance = np.square(point_1[0] - point_2[0]) + np.square(point_1[1] - point_2[1])cosin = (square_distance - square_distance_1 - square_distance_2) / (2 * np.sqrt(square_distance_1 * square_distance_2))square_sin = 1 - np.square(cosin)square_sin = np.nan_to_num(square_sin)result = np.sqrt(square_distance_1 * square_distance_2 * square_sin / square_distance)result[cosin < 0] = np.sqrt(np.fmin(square_distance_1, square_distance_2))[cosin < 0]  # 这一步是为什么?# self.extend_line(point_1, point_2, result)return result

Loss函数

概率图和二值图共享标签,Loss也都采用BCE loss,(官方实现代码中二值图用的dice loss),并且用了1:3的OHEM。阈值图用的L1 loss。

后处理

inference阶段既可以使用概率图也可以使用二值图来得到完整的文本实例,用概率图可以省去生成阈值图和二值图的操作,加快了速度,且效果和用二值图也没差。

PSENet是通过学习多个不同大小的kernel,从小到大依次扩张kernel得到完整的文本实例。DBNet因为有阈值监督的存在,kernel区域可以学习的更好,因此可以按照制作标签时的缩放比例反向扩张回去直接得到完整的文本实例。

场景文本检测算法 可微分二值化DBNet原理与代码解析相关推荐

  1. 高达82 fps的实时文本检测,华科AAAI2020提出可微分二值化模块

    点击我爱计算机视觉标星,更快获取CVML新技术 今天跟大家分享一篇近几天公布的关于实时场景文本检测的论文Real-time Scene Text Detection with Differentiab ...

  2. 高达82 fps的实时文本检测,可微分二值化模块

    高达82 fps的实时文本检测,可微分二值化模块 https://github.com/MhLiao/DB Real-time Scene Text Detection with Differenti ...

  3. 图像识别算法研究(1)---二值化概述---2011-03-14

    我们遇到的识别图片,经常被认为的加入杂色干扰,形成一个浓淡分布不均的多值图像.把这样一幅多灰度值的图像(Gray Level Image)转化为只有黑(前景文字部分)白(背景部分)分布的二值图像(Bi ...

  4. OTSU算法对图像二值化

    出处:http://blog.csdn.net/WuHaibing_CVer OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法. 1. OTSU算法原理简介 对于一幅图 ...

  5. 智能车视觉处理系列文章——二值化技巧(含代码)

    文章目录 图片二值化技巧 1. 大津法(OTSU) 求阈值 1.1 说明 1.2 计算过程 图片二值化技巧 1. 大津法(OTSU) 求阈值 1.1 说明 ​ 为了解决不同光照条件下,二值化阈值不同的 ...

  6. 利用最大熵进行阈值分割从而实现灰度图像的二值化的原理概要及OpenCV代码

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 详细的数学原理目前我也没搞明白,所以只说下原理概 ...

  7. 微信QQ的二维码登录原理js代码解析

    这篇文章主要大家详细解析了微信QQ的二维码登录原理js代码, 具有一定的参考价值,感兴趣的小伙伴们可以参考一下 在很多地方就是都出现了使用二维码登录,二维码付款,二维码账户等应用(这里的二维码种马,诈 ...

  8. 连通域最小外接矩形算法原理_基于分割的文本检测算法之PSENet/PAN/DBNet

    1. 文本检测难点 文本内包含文本,艺术字体,任意方向 ,曲线文字 ,多语言,其他环境因素等是文本检测中的难点 2. 分割 问题1: 语义分割模型是对pixel进行分类,所以理论上讲,可以检测不规则的 ...

  9. 基于深度学习的场景文本检测和识别(Scene Text Detection and Recognition)综述

    1. 引言 文字是人类最重要的创作之一,它使人们在时空上可以有效地.可靠的传播或获取信息. 场景中的文字的检测和识别对我们理解世界很有帮助,它应用在图像搜索.即时翻译.机器人导航.工业自动化等领域. ...

最新文章

  1. Silverlight实用窍门系列:52.Silverlight中的MVVM框架极速入门(以MVVM Light Toolkit为例)...
  2. php mysql特殊符号过滤微信小程序_微信小程序数据过滤(filter)方法
  3. ISO9000管理体系认证申请书
  4. maven 打包时动态替换properties资源文件中的配置值
  5. 【Java】 Java反射机制总结
  6. CSS中超链接样式的书写顺序
  7. 链表的基本操作Basic Operation of LinkList
  8. 使用webbench进行压力测试
  9. 批量梯度下降算法BGD
  10. 1.恶意软件中的防双开
  11. Nexus下载网盘地址,免费哦,烦要币的
  12. 个人邮箱怎么在微信里登陆?
  13. 【理财】3.富人思维
  14. javaEE核心框架之 Mybatis ( 一 )
  15. 音频文件 数据库存储_Apache Kafka是数据库吗?
  16. Amber中的NMR restraint中的一些参数的设置的意义
  17. Android设备获取mp3中的专辑封面信息
  18. 《C语言内涵教程》前言
  19. anaconda conda 换源
  20. 关于湖南卫视正在播放的TVB剧

热门文章

  1. 计算机网络——数据链路层介质访问控制
  2. 京东登陆界面正则匹配
  3. thinkphp项目_简历网站
  4. 支付宝快捷登录相关事宜
  5. LT8522EX 是 Lontium 的矩阵开关芯片基于两路输入,输出 (VGA 和 HDMI)
  6. nRF52832调试
  7. Python——下载音乐(干货)
  8. 个人笔记,深入理解 JVM,很全!
  9. airplay服务器linux,树莓派搭建AirPlay服务实现WiFi无线音响外放
  10. Java流程控制相关知识(四)