DBNet 解析

1. 背景介紹

文本檢測分為基于回歸和基于分割兩種方法,DBNet 的原理是基于分割算法杠娱。對于一般分割算法流程:先通過網(wǎng)絡(luò)輸出文本分割的概率圖澡绩,然后使用設(shè)定閾值將概率圖轉(zhuǎn)化為二值圖,然后通過后處理得到檢測結(jié)果(文本框坐標)挽拔。但是缺點在于閾值的選取非常關(guān)鍵酌毡。

DBNet 針對這個問題克握,提出可微分二值化的概念:即對每一個像素點進行自適應(yīng)二值化,二值化閾值由網(wǎng)絡(luò)學(xué)習得到枷踏,徹底將二值化這一步驟加入到網(wǎng)絡(luò)里一起訓(xùn)練菩暗,這樣最終的輸出圖對于閾值就會非常魯棒。

自適應(yīng)閾值

上圖中藍線部分就是傳統(tǒng)的文本檢測算法流程:

  • 首先旭蠕,通過設(shè)置一個固定閾值將分割網(wǎng)絡(luò)訓(xùn)練得到的概率圖(segmentation map)轉(zhuǎn)化為二值圖(binarization map)停团。
  • 然后,使用一些啟發(fā)式技術(shù)(例如像素聚類)將像素分組為文本實例掏熬。

上圖紅色部分就是 DBNet 的算法流程:

通過分割網(wǎng)絡(luò)獲取概率圖和閾值圖佑稠,閾值圖是網(wǎng)絡(luò)預(yù)測得出,并不是固定的值旗芬,這樣就可以很好將背景與前景分離出來舌胶,但是這樣的操作會給訓(xùn)練帶來梯度不可微的情況,對此對于二值化提出了一個叫做 Differentiable Binarization來解決不可微的問題疮丛。

2. DBNet 算法整體架構(gòu)

上圖是 DBNet 模型網(wǎng)絡(luò)結(jié)構(gòu)示意圖幔嫂,主要分為 3 個模塊:

  • 第一模塊(1):左邊的紅框使用的是一個 FPN 結(jié)構(gòu),分為自底向上的卷積操作與自頂向下的上采樣誊薄,以此來獲取多尺度的特征婉烟。1 圖下面部分是 3x3 的卷積操作,按照卷積公式分別獲取原圖大小比例的 1/2暇屋、1/4、1/8洞辣、1/16咐刨、1/32 的特征圖;然后自頂向下進行上采樣 x2扬霜,然后與自底向上生成的相同大小的特征圖融合定鸟;融合之后再采用 3x3 的卷積消除上采樣的混疊效應(yīng);最后對每層輸出結(jié)果進行上采樣著瓶,統(tǒng)一為 1/4 大小的特征圖联予。
  • 第二模塊(2):將 1/4 大小的特征圖經(jīng)過一系列卷積和轉(zhuǎn)置卷積的機構(gòu)獲取概率圖 P 和閾值圖 T,可參考 FCN 網(wǎng)絡(luò)結(jié)構(gòu),目的是生成與原圖一樣大小的特征圖 P 和 T沸久。
  • 第三模塊(3):將特征圖 P 和 T 經(jīng)過 DB 方法(后續(xù)介紹)得到近似二值圖季眷。

經(jīng)過上面三個模塊,可以得到概率圖卷胯、閾值圖和近似二值圖子刮。在訓(xùn)練過程中,對這三個圖進行監(jiān)督學(xué)習窑睁,更新各個模塊的參數(shù)挺峡。在推理過程中,直接使用概率圖担钮,然后使用固定閾值獲取結(jié)果橱赠。

下面介紹可微二值化的發(fā)展流程:

標準二值化
在傳統(tǒng)的圖像分割算法中,我們獲取概率圖后箫津,會使用標準二值化(Standard Binarize)方法進行處理狭姨,將低于閾值的像素點置0,高于閾值的像素點置1鲤嫡,公式如下:
B_{i, j}=\left\{\begin{array}{c} 1, \text { if } P_{i, j}>=t \\ 0, \text { otherwise } \end{array}\right.
t 是預(yù)先設(shè)置的閾值送挑,(i,j)代表的是像素點坐標位置∨郏可見標準的二值化是不可微的惕耕,所以也就無法放入到網(wǎng)絡(luò)中進行優(yōu)化學(xué)習。

可微二值化
可微二值化就是將標準二值化中的階躍函數(shù)進行了近似诫肠,公式如下所示:
\hat{\boldsymbol{B}}=\frac{1}{1+e^{-k\left(P_{i, j} - T_{i, j}\right)}}
可微二值化本質(zhì)上是一個 帶系數(shù) k 的 sigmoid 函數(shù)司澎,取值范圍為(0,1),k 是膨脹因子(經(jīng)驗型設(shè)置為50)栋豫。P_{i,j} 是指概率圖像素點挤安,T_{i,j} 是指閾值圖像素點。

標準二值化和可微二值化的對比如下圖 (a) 所示丧鸯,SB 曲線代表標準二值化蛤铜,DB 代表可微二值化,可以看到曲線變得更為平滑丛肢,也就是可微:

除了可微之外围肥,DB 方法也會改善算法的性能,在反向傳播是梯度的計算上進行觀察蜂怎。當使用交叉熵損失(y=1代表文字區(qū)域)時穆刻,正負樣本的 loss 分別為 l_+l_-,公式如下:
交叉熵損失函數(shù):L=-[y \log \hat{B}+(1-y) \log (1-\hat{B})] \\正樣本(y=1)損失:l_{+}=-\log \left(\frac{1}{1+e^{-k\left(P_{i, j}-T_{i, j}\right)}}\right) \\負樣本(y=0)損失:l_{-}=-\log \left(1-\frac{1}{1+e^{-k\left(P_{i, j}-T_{i, j}\right)}}\right)

對輸入 x = P_{i, j}-T_{i, j} 求偏導(dǎo)杠步,則會得到:
\frac{\delta l_{+}}{\delta x}=-k f(x) e^{-k x}, \\ \frac{\delta l_{-}}{\delta x}=-k f(x) ,

可以看到 增強因子k 對于錯誤預(yù)測對梯度的影響變大了氢伟,從而可以促進模型的優(yōu)化過程產(chǎn)生更為清晰的預(yù)測結(jié)果榜轿。對于x>0時,按照(a)圖屬于正樣本(文字區(qū)域)朵锣,x<0時屬于負樣本(非文字區(qū)域)谬盐。
上圖(b)是指 l_{+} 的導(dǎo)數(shù)曲線,如果發(fā)生漏報(正樣本被預(yù)測為負樣本x<0)猪勇,圖(b)小于 0 的部分導(dǎo)數(shù)非常大设褐,證明損失也是非常大的,則更能清晰的進行梯度回傳泣刹。同理助析,圖(c)代表 l_{-}的導(dǎo)數(shù)曲線,當發(fā)生誤報(負樣本被預(yù)測為正樣本x>0)椅您,導(dǎo)數(shù)也是非常大的外冀,損失也比較大。

3. 真實標簽生成

DB 網(wǎng)絡(luò)中掀泳,訓(xùn)練過程中網(wǎng)絡(luò)有 3 個輸出:概率圖雪隧、閾值圖和近似二值圖:

  • 概率圖:圖中每個像素點的值為該位置屬于文本區(qū)域的概率。
  • 閾值圖:圖中每個像素點的值為該位置的二值化閾值员舵。
  • 近似二值圖:由概率圖和閾值圖通過 DB 算法計算得到脑沿,圖中像素的值為 0 或 1。

概率圖的標簽 G_{s}和閾值圖標簽G_o6yiqig马僻,DB 網(wǎng)絡(luò)參考 PSENet 中的方法庄拇,使用擴張和收縮的方式構(gòu)建閾值圖和概率圖。在該方法中韭邓,對于一幅文字圖像措近,文本區(qū)域的每個多邊形使用一組線段G=\left\{S_{k}\right\}_{k=1}^{n} 來進行描述, n 為線段個數(shù)女淑。

概率圖標簽G_{s}
對于概率圖和近似二值圖來說瞭郑,使用收縮的方式構(gòu)建標簽(Vatti clipping算法),收縮的偏移量D由多邊形的周長 L 和面積 A 計算得到鸭你,公式如下:其中屈张, r 是收縮因子,實驗中經(jīng)驗設(shè)置為 0.4 袱巨。
D=\frac{A\left(1-r^{2}\right)}{L}

閾值圖標簽G_wa8q84a

  • 首先使用G_{s}計算過程中的偏移量 D 進行多邊形的擴充阁谆。得到G_{s}G_igyc8ec之間的區(qū)域。
  • 計算之間區(qū)域到原始框的距離瓣窄,并得到最近邊(長方形就是 4 條邊)的距離。最外面的大框線上區(qū)域和最里面的小框線上區(qū)域計算為 D 纳鼎,原始框位置的距離為 0俺夕。
  • 進行第一次的歸一化(除以D)裳凸,這樣距離控制到 [0,1] 之間,并且最中間的區(qū)域越接近0劝贸,越里面和越外面的區(qū)域越接近1姨谷。然后使用 1-X 操作,讓越中心的距離為 1映九,越邊緣的距離為 0梦湘。(這樣圖片顯示就是中間亮兩頭暗)。
  • 最終再進行縮放件甥,比如歸一化到 [0.3捌议,0.7] 的值。

4. 損失函數(shù)

由于在訓(xùn)練階段輸出 3 個預(yù)測圖(大小與原圖一致)引有,所以在損失函數(shù)中瓣颅,也需要有對應(yīng)的真實標簽去構(gòu)建 3 部分損失函數(shù)∑┱總的損失函數(shù)的公式定義如下:
L=L_宫补+\alpha \times L_{s}+\beta \times L_{t}
其中,L為總的損失曾我,L_粉怕為近似二值圖的損失,使用 Dice 損失抒巢;L_{s}為概率圖損失贫贝,使用帶 OHEM 的 Dice 損失;L_{t}為閾值圖損失虐秦,使用預(yù)測值和標簽間的 ??1 距離平酿。其中,?? 和 ?? 為權(quán)重系數(shù)悦陋。
接下來分析這 3 個loss:
1)首先是Dice Loss蜈彼,Dice Loss是比較預(yù)測結(jié)果跟標簽之間的相似度,常用于二值圖像分割俺驶。
diceloss =1-\frac{2 \times intersection area }{total area}
2)其次是MaskL1 Loss幸逆,是計算預(yù)測值和標簽間的??1距離
3)最后是Balance Loss,是帶OHEM的Dice Loss暮现,目的是為了改善正負樣本不均衡的問題。OHEM 為一種特殊的自動采樣方式栖袋,可以自動的選擇難樣本進行l(wèi)oss的計算拍顷,從而提升模型的訓(xùn)練效果。

Dice Loss (遷移)
dice loss=1-\frac{2|X \bigcap Y|}{|X|+|Y|}
其中 |X∩Y| 是X和Y之間的交集塘幅,|X|和|Y|分表表示X和Y的元素的個數(shù)昔案,其中尿贫,分子的系數(shù)為2,是因為分母存在重復(fù)計算X和Y之間的共同元素的原因踏揣。
同時庆亡,一般會加入平滑因子,防止分子分母全為0捞稿。對于分割任務(wù)而言又谋,|X| 和 |Y| 代表分割的 ground truth 和 predict_mask。

計算步驟:

  • 首先娱局,使用預(yù)測圖 predict_mask 和 ground truth 之間的點乘彰亥。


  • 逐元素相乘的結(jié)果元素的相加和。


  • 計算|X|和|Y|铃辖,這里可以采用直接元素相加剩愧,也可以采用元素平方求和的方法:


5. 模型訓(xùn)練流程

以 PaddleOCR (https://github.com/PaddlePaddle/PaddleOCR/blob/0791714b91/deploy/lite/readme.md) 為例,模型的訓(xùn)練流程分為以下部分:

  • 數(shù)據(jù)預(yù)處理:主要包括解析圖片娇斩、真實標簽處理仁卷、隨機裁剪和圖片增強。
  • 模型結(jié)構(gòu)部分:分為 Backbone犬第、Neck锦积、Head 部分。
  • loss 部分:分為 概率圖 L_{s}歉嗓、閾值圖 L_{t}丰介、近似二值圖 L_鉴分。
  • metric 部分:經(jīng)過后處理之后進行評價指標的計算哮幢。

5.1 數(shù)據(jù)預(yù)處理
數(shù)據(jù)預(yù)處理包含以下部分:
DecodeImage 解析圖片、DetLabelEncode 解析 label 文件志珍、IaaAugment 進行數(shù)據(jù)增強橙垢、EastRandomCropData 隨機裁剪(裁剪到指定 size (960, 960, 3))、MakeBorderMap 閾值圖真實標簽生成(batch, 960, 960)伦糯、MakeShrinkMap 概率圖標簽生成(batch, 960, 960)柜某、NormalizeImage 歸一化、ToCHWImage 緯度變化為(3, 960, 960)敛纲、KeepKeys 指定格式喂击。

經(jīng)過數(shù)據(jù)預(yù)處理 image 字段的大小變?yōu)椋╞atch, 3, 960, 960)。

5.2 模型前向傳播
模型依次經(jīng)過 backbone(MobileNetV3)--> neck(DBFPN) --> head(DBHead) 步驟淤翔,緯度變化如下所示:

輸入的 images size: [2, 3, 960, 960]翰绊,batch 為 2
backbone 輸出1:backbone behind [2, 16, 240, 240],尺寸對應(yīng) 1/4
backbone 輸出2:backbone behind [2, 24, 120, 120],尺寸對應(yīng) 1/8
backbone 輸出3:backbone behind [2, 56, 60, 60]监嗜,尺寸對應(yīng) 1/16
backbone 輸出4:backbone behind [2, 480, 30, 30]琳要,尺寸對應(yīng) 1/32
neck 輸出:neck behind [2, 96, 240, 240],輸出 1/4
head 輸出:head behind [2, 3, 960, 960]秤茅,與原圖大小一致,分別代表 shrink_maps, threshold_maps, binary_maps童叠,大小都為 [960, 960]

5.3 后處理
后處理的邏輯流程如下:

  • 首先框喳,對概率圖進行固定閾值處理,得到分割圖厦坛。
  • 對分割圖計算輪廓五垮,遍歷每個輪廓,去除太小的預(yù)測杜秸;對每個輪廓計算包圍矩形放仗,然后計算該矩形的預(yù)測score。
  • 對矩形進行反向shrink操作撬碟,得到真實矩形大械ぁ;最后還原到原圖 size 就可以了呢蛤。

下面對 python 代碼進行解析:
pred 是模型的輸出惶傻,shape 為 (1,height, weight)其障,訓(xùn)練階段都為(1银室,960,960)励翼,推理階段則不一定蜈敢。

查看 boxes_from_bitmap 的代碼:

def boxes_from_bitmap(self, pred, _bitmap, dest_width, dest_height):
        '''
        _bitmap: single map with shape (1, H, W),
                whose values are binarized as {0, 1}
        '''

        bitmap = _bitmap
        height, width = bitmap.shape
        
        # findContours 獲取輪廓,如長方形獲取四點頂點坐標
        outs = cv2.findContours((bitmap * 255).astype(np.uint8), cv2.RETR_LIST,
                                cv2.CHAIN_APPROX_SIMPLE)
        # py2汽抚、py3 不同版本的情況
        if len(outs) == 3:
            img, contours, _ = outs[0], outs[1], outs[2]
        elif len(outs) == 2:
            contours, _ = outs[0], outs[1]
        
        # 文本框最大數(shù)量
        num_contours = min(len(contours), self.max_candidates)

        boxes = []
        scores = []
        for index in range(num_contours):
            contour = contours[index]
            #  計算最小包圍矩抓狭,獲取四個坐標點,左上為起點(順時針)
            points, sside = self.get_mini_boxes(contour)
            # 長方形中寬高最小值過濾
            if sside < self.min_size:
                continue
            points = np.array(points)
            # 利用 points 內(nèi)部預(yù)測概率值殊橙,計算出一個score,作為實例的預(yù)測概率
            score = self.box_score_fast(pred, points.reshape(-1, 2))
            # score 得分的過濾
            if self.box_thresh > score:
                continue
            # shrink反向還原辐宾,之前概率圖進行了縮放,故還原
            box = self.unclip(points).reshape(-1, 1, 2)
            box, sside = self.get_mini_boxes(box)
            if sside < self.min_size + 2:
                continue
            box = np.array(box)
            
            # 還原到原始坐標膨蛮,反向還原之后叠纹,還需要還原到原始圖片(原始圖片在預(yù)處理時被縮放處理)
            box[:, 0] = np.clip(
                np.round(box[:, 0] / width * dest_width), 0, dest_width)
            box[:, 1] = np.clip(
                np.round(box[:, 1] / height * dest_height), 0, dest_height)
            boxes.append(box.astype(np.int16))
            scores.append(score)
        return np.array(boxes, dtype=np.int16), scores

def get_mini_boxes(self, contour):
        # 返回點集 cnt 的最小外接矩形:# 得到最小外接矩形的(中心(x,y), (寬,高), 旋轉(zhuǎn)角度)
        bounding_box = cv2.minAreaRect(contour)
        # 排序,最終以左上的坐標為起點敞葛,順時針排列四個坐標點
        points = sorted(list(cv2.boxPoints(bounding_box)), key=lambda x: x[0])

        index_1, index_2, index_3, index_4 = 0, 1, 2, 3
        if points[1][1] > points[0][1]:
            index_1 = 0
            index_4 = 1
        else:
            index_1 = 1
            index_4 = 0
        if points[3][1] > points[2][1]:
            index_2 = 2
            index_3 = 3
        else:
            index_2 = 3
            index_3 = 2

        box = [
            points[index_1], points[index_2], points[index_3], points[index_4]
        ]
        return box, min(bounding_box[1])

6. 模型推理流程

如果不考慮 label誉察,則其處理邏輯和訓(xùn)練邏輯有一點不一樣,其把圖片統(tǒng)一 resize 到指定的長度進行預(yù)測惹谐。

數(shù)據(jù)預(yù)處理
數(shù)據(jù)預(yù)處理沒有訓(xùn)練階段的數(shù)據(jù)增強持偏、隨機裁剪和生成標簽部分驼卖,但是會存在一個 resize 的操作,將寬高設(shè)置為 32 的倍數(shù)鸿秆。

DetResizeForTest 步驟如下:
1)對圖片進行等比例的放縮酌畜,設(shè)置最大的尺寸為 960。如 3 張圖片分別為 (720卿叽,1280)桥胞、(230,230)考婴、(1150贩虾,720)。
2)對圖片進行放縮沥阱,以最大邊為準(操作960的直接放縮到 960)缎罢,縮小至能被 32 整除的最大尺寸。則輸出:(512考杉,960策精,3)、(224崇棠,224蛮寂,3)、(960易茬,576酬蹋,3)。由于寬高都為 32 的倍數(shù)抽莱,則放縮的比例不統(tǒng)一范抓,但盡可能相差不大。

后續(xù)的操作就與訓(xùn)練階段一致食铐,通過網(wǎng)絡(luò)結(jié)構(gòu)匕垫,然后進行后處理獲得結(jié)果。

7. 參考文獻

  1. Real-time Scene Text Detection with Differentiable Binarization
  2. PaddlePaddle DBNet 介紹
  3. DBNet 詳解
  4. DBNet論文閱讀筆記(附論文和源碼地址)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虐呻,一起剝皮案震驚了整個濱河市象泵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斟叼,老刑警劉巖偶惠,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朗涩,居然都是意外死亡忽孽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兄一,“玉大人厘线,你說我怎么就攤上這事〕龈铮” “怎么了造壮?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長骂束。 經(jīng)常有香客問我费薄,道長,這世上最難降的妖魔是什么栖雾? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮伟众,結(jié)果婚禮上析藕,老公的妹妹穿的比我還像新娘。我一直安慰自己凳厢,他們只是感情好账胧,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著先紫,像睡著了一般治泥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上遮精,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天居夹,我揣著相機與錄音,去河邊找鬼本冲。 笑死准脂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的檬洞。 我是一名探鬼主播狸膏,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼添怔!你這毒婦竟也來了湾戳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤广料,失蹤者是張志新(化名)和其女友劉穎砾脑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艾杏,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拦止,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汹族。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡萧求,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出顶瞒,到底是詐尸還是另有隱情夸政,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布榴徐,位于F島的核電站守问,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坑资。R本人自食惡果不足惜耗帕,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望袱贮。 院中可真熱鬧仿便,春花似錦、人聲如沸攒巍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柒莉。三九已至闻坚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兢孝,已是汗流浹背窿凤。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跨蟹,地道東北人卷玉。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像喷市,于是被迫代替她去往敵國和親相种。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容