2.基于分割的文本检测算法--DBNet

本文介绍了XiangBai等人2019年提出的实时文本检测方法,重点在于DifferentiableBinarization(DB)技术,它允许模型在训练时端到端地处理二值化过程,提高了检测速度和准确性。模型包含全卷积结构,输出分割概率图和阈值图,通过可微分的二值化操作简化后处理步骤。此外,文章讨论了自适应阈值、标签生成和模型优化策略,如使用二分类交叉熵损失和L1损失函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


1.基本情况

论文:Real-time Scene Text Detection with Differentiable Binarization
代码:DB

2019年11月华中科技大学的Xiang Bai等提出的方法。

基于分割的文本检测方法对分割结果的概率图进行二值化后处理,然后来提取文本区域,可以检测任意形状的文本区域。但基于分割的文本检测算法一般都需要复杂的后处理,影响推理的性能。

在这里插入图片描述

上图中,蓝色的路径表示传统的基于分割的文本检测,完整流程包括得到分割概率图,使用阈值二值化,然后通过像素聚类等手段得到最终的文本检测结果,红色路径是作者提出的新的方法,同时输出分割概率图和进行二值化使用的阈值图,之后使用一个可微分的二值化操作求得二值化的图像,其中虚线表示操作只发生在预测阶段,实线表示在训练和预测阶段都会发生。阅读源码可以发现,与上图中描述不同,训练阶段的二值化结果是通过可微分的二值化操作得到的,预测阶段的二值化结果仍然使用的是固定阈值来计算的。

在这篇论文中,作者主要的创新点就是提出了可微分二值化运算(Differentiable Binarization, DB),DB的引入使得在训练时可以将二值化操作放入模型中,从而实现模型的端到端训练,简化后处理,加快运算速度。

2.主要工作

2.1 模型架构

在这里插入图片描述

从上图中可以看到网络使用了全卷积结构,将多个尺度的特征图使用FPN直接进行融合,经过上采样得到同样大小的特征图进行concatenate拼接,经过两个分支,一个输出分割概率图,一个输出阈值图,使用这两个结果,输入到DB运算中得到近似二值图,对二值图处理得到文本区域。

2.2 二值化

backbone提取的特征图为 F F F,表示分割结果的概率图为 P P P,阈值图为 T T T,通过 P P P F F F计算得到的阈值图为 B ^ \hat{B} B^

标准二值化:给定表示分割结果的概率图 P ∈ R H × W P\in R^{H\times W} PRH×W H / W H/W H/W表示图的高/宽,标准二值化操作可表示成:

B i , j = { 1 , i f   P i , j ≥ t 0   o t h e r w i s e B_{i,j}=\left\{\begin{matrix} 1 ,if\, P_{i,j} \ge t\\ 0\, otherwise \end{matrix}\right. Bi,j={1,ifPi,jt0otherwise

上式中 t t t是预定义的阈值, i , j i,j i,j表示的图中像素的坐标。

可微分二值化:从公式可以看出标准二值化是不可微的,因此使用标准二值化在网络的训练中不能直接对其进行优化。作者提出了可微分二值化运算:

B i , j ^ = 1 1 + e − k ( P i , j − T i , j ) \hat{B_{i,j}}=\frac{1}{1+e^{-k(P_{i,j}-T_{i,j})}} Bi,j^=1+ek(Pi,jTi,j)1

B i , j ^ \hat{B_{i,j}} Bi,j^是近似二值化的值, T T T是网络学习得到的自适应阈值, k k k是放大系数,取一个经验值为 50 50 50

在这里插入图片描述

上图(a)中表示的是标准二值化 S B SB SB和可微分二值化 D B DB DB的曲线图,可以看到二者由几乎一样的取值。

为什么可微分二值化有助于网络的学习呢?

定义 x = P i , j − T i , j x=P_{i,j}-T_{i,j} x=Pi,jTi,j,则可微二值化运算可表示为 f ( x ) = 1 1 + e − k x f(x)=\frac{1}{1+e^{-kx}} f(x)=1+ekx1,对于可微二值化的输出使用二分类交叉熵损失函数: l b c e = − y t r u e l o g ( y p r e ) − ( 1 − y t r u e ) l o g ( 1 − y p r e ) l_{bce}=-y_{true}log(y_{pre})-(1-y_{true})log(1-y_{pre}) lbce=ytruelog(ypre)(1ytrue)log(1ypre)前半部分是正样本 y t r u e = 1 y_{true}=1 ytrue=1的损失,后半部分是负样本 y t r u e = 0 y_{true}=0 ytrue=0的损失,则可微分二值化运算输出的正负样本的损失为:

l + = − l o g 1 1 + e − k x l_{+}=-log\frac{1}{1+e^{-kx}} l+=log1+ekx1

l − = − l o g ( 1 − 1 1 + e − k x ) l_-=-log(1-\frac{1}{1+e^{-kx}}) l=log(11+ekx1)

l + / l − l_+/l_- l+/l分别求梯度为:

∂ l + ∂ x = − k f ( x ) e − k x \frac{\partial l_+}{\partial x} = -kf(x)e^{-kx} xl+=kf(x)ekx

∂ l − ∂ x = k f ( x ) \frac{\partial l_-}{\partial x} = kf(x) xl=kf(x)

上图中(b)和©分别表示 l + l_+ l+ l − l_- l的导数,从导数表达式中可以看出梯度被放大了 k k k倍,特别是对类别预测错误的样本 x < 0 , l + x\lt 0, l_+ x<0,l+ x > 0 , l − x\gt 0, l_- x>0,l梯度放大作用更明显,这样可以使模型产生更有区分度的预测结果。

2.3 自适应阈值

从上面的介绍中可看到自适应阈值图和文本边框有些相似,但自适应阈值图通过有监督或无监督的训练都能获得。

在这里插入图片描述

上图中(a)原图,(b)是分割结果的概率图,©是无监督得到的阈值图,(d)是有监督训练得到的阈值图

2.4 标签生成

在这里插入图片描述

文本的阈值图中的边框不应该是文本的一部分,在进行网络训练之前需先将文本标签轮廓进行扩展,扩展的距离通过以下公式计算:

D = A ( 1 − r 2 ) L D=\frac{A(1-r^2)}{L} D=LA(1r2)

r r r是缩放的比率,经验值取0.4, A A A是原始文本区域多边形面积, L L L是轮廓周长,D是扩展距离。源代码中对文本检测区域的处理使用的pyclipper.PyclipperOffset(),具体可参考

因为训练时对标签的处理,在推理时还需要将扩展的部分缩减掉。

2.5 模型优化

总的损失函数表示为:

L = L s + α × L b + β × L t L = L_s + \alpha \times L_b + \beta \times L_t L=Ls+α×Lb+β×Lt

其中, L s L_s Ls是分割概率图对应的损失, L b L_b Lb二值化图对应的损失, L t L_t Lt是阈值图对应的损失, α = 1.0 , β = 10 \alpha=1.0,\beta=10 α=1.0,β=10

对于概率图和二值化图使用的是二分类交叉熵损失函数:

L s = L b = ∑ i ∈ S l y i l o g x i + ( 1 − y i ) l o g ( 1 − x i ) L_s=L_b=\sum_{i\in S_l}y_ilog x_i+(1-y_i)log(1-x_i) Ls=Lb=iSlyilogxi+(1yi)log(1xi)

其中 S l S_l Sl是为应对不平衡问题使用Hard Negative Mining算法得到的采样样本,正负样本比例为 1 : 3 1:3 1:3

L t L_t Lt使用 L 1 L_1 L1距离来计算:

L t = ∑ i ∈ R d ∣ y i ∗ − x i ∗ ∣ L_t = \sum_{i\in R_d}|y_i^*-x_i^*| Lt=iRdyixi

R d R_d Rd是扩充之后文本区域的像素坐标, y i ∗ y_i^* yi是阈值图的标签。

3.源码

第一部分介绍时提到,DB只应用在训练时,推理时使用的还是常规的固定阈值二值化方法,从模型的forward函数可以看到:

decoders/seg_detector.py

class SegDetector(nn.Module):
     ...
    def forward(self, features, gt=None, masks=None, training=False):
        c2, c3, c4, c5 = features
        in5 = self.in5(c5)
        in4 = self.in4(c4)
        in3 = self.in3(c3)
        in2 = self.in2(c2)

        out4 = self.up5(in5) + in4  # 1/16
        out3 = self.up4(out4) + in3  # 1/8
        out2 = self.up3(out3) + in2  # 1/4

        p5 = self.out5(in5)
        p4 = self.out4(out4)
        p3 = self.out3(out3)
        p2 = self.out2(out2)

        fuse = torch.cat((p5, p4, p3, p2), 1)
        # this is the pred module, not binarization module; 
        # We do not correct the name due to the trained model.
        binary = self.binarize(fuse)
        if self.training:
            result = OrderedDict(binary=binary)
        else:
            return binary
        if self.adaptive and self.training:
            if self.serial:
                fuse = torch.cat(
                        (fuse, nn.functional.interpolate(
                            binary, fuse.shape[2:])), 1)
            thresh = self.thresh(fuse)
            thresh_binary = self.step_function(binary, thresh)
            result.update(thresh=thresh, thresh_binary=thresh_binary)
        return result

    def step_function(self, x, y):
        return torch.reciprocal(1 + torch.exp(-self.k * (x - y)))


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值