百度飛槳(PaddlePaddle) - PaddleOCR 文字識別簡單使用
影像二值化



影像二值化( Image Binarization),指將影像上的像素點灰度值設為0或255,將整個影像呈現出明顯的黑白效果程序,二值影像每個像素只有兩種取值:要么純黑,要么純白
影像二值化,有利于影像的進一步處理, 使影像變得簡單,資料量減少(256位的灰度圖,共有256級,變成黑白影像后,只有2級),能凸顯出感興趣的目標輪廓,然后進行二值影像的處理與分析
閾值法是指選取一個數字,大于它就視為全白,小于它就視為全黑,0代表全黑,255代表全白
所有灰度大于或等于閥值的像素,被判定為屬于特定物體,其灰度值為255表示,
否則這些像素點被排除在物體區域以外,灰度值為0,表示背景或者例外的特體區域
OpenCV (固定伐值)
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import cv2
# Load image
img = cv2.imread('images/006.jpg')
# Apply thresholding
binary = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY)[1]
save_file = './ocr_result/binary_image.jpg'
# Save output image
cv2.imwrite(save_file, binary)
# 顯示圖片--二分值
img1 = mpimg.imread(save_file)
plt.figure(figsize=(10, 10))
plt.imshow(img1)
plt.axis('off')
plt.show()

文本檢測

基于分割的做法(如藍色箭頭所示):
傳統的pipeline使用固定的閾值對于分割后的熱力圖進行二值化處理【見上文】
- 首先,它們設定了固定的閾值,用于將分割網路生成的概率圖轉換為二進制影像
- 然后,用一些啟發式技術(例如像素聚類)用于將像素分組為文本實體
DB的做法(如紅色箭頭所示):
而本文提出的pipeline會將二值化操作嵌入到分割網路中進行組合優化,會生成與熱力圖對應的閾值圖,通過二者的結合生成最終的二值化操作,
- 在得到 分割map后,與網路生成的threshold map一次聯合做可微分二值化得到二值化圖,然后再經過后處理得到最終結果,
- 將二值化操作插入到分段網路中以進行聯合優化,通過這種方式,可以自適應地預測影像每個位置的閾值,從而可以將像素與前景和背景完全區分開, 但是,標準二值化函式是不可微分的,因此,我們提出了一種二值化的近似函式,稱為可微分二值化(DB),當訓練時,該函式完全可微分,將一個固定的閾值訓練為一個可學習的每個位置的閾值
標簽生成
首先看label是如何生成的,網路要學習的目標gt 與 threshold map是怎樣的生成和指導網路去訓練的,知道threshold_map的label值跟gt的值,我們才能更好地去理解“可微分二值化”是如何實作的;

給定一張文字影像,其文本區域的每個多邊形由一組線段描述:
\(\ G = \{s_k\}^n_{k = 1}\)
其中,n表示頂點的數量
使用Vatti clipping algorithm (Vati 1992)縮小多邊形,對 gt 多邊形(polygon) 進行縮放;收縮偏移量(offset of shrinking)\(D\) 可以通過周長 \(L\) 和面積 \(A\) 計算:
\(\ D = \frac {A(1-r^2)}{L}\)
其中,\(r\) 是縮放比例,依經驗一般取值為 0.4
- 這樣我們就通過 gt polygon 形成 縮小版的 polygon 的gt mask圖 probability map(藍色邊界)
- 以同樣的 offset D 從多邊形polygon \(G\) 拓展到 \(G_d\) ,得到如圖中 threshold_map中的(綠色邊界)
threshold_map中由 \(G_s\) 到 \(G_d\) 之間形成了一個文字區域的邊界,
一組圖來可視化影像生成的結果:

我們可以看到 probability map 的 gt 是一個完全的0,1 mask ,polygon 的縮小區域為1,其他背景區域為0;
但是在threshold_map文字邊框值并非0,1;
使用PyCharm的view array 我們能看到threshold_map中文字邊框的數值資訊:

文字最外圈邊緣為0.7,靠近中心區域是為0.3的值,(0.3-0.7為預設的閾值最大最小值),我們可以看到文字邊界為閾值最大,然后根據文字實體邊緣距離逐漸遞減,
知道threshold_map的label值跟gt的值,我們才能更好地去理解“可微分二值化”是如何實作的;
獲取邊界框

整體流程如圖所示:
- backbone網路提取影像特征
- 類似FPN網路結構進行影像特征融合后得到兩個特征圖 probability map 跟 threshold map
- probability map 與threshold map 兩個特征圖做DB差分操作得到文字區域二分圖
- 二分圖經過cv2 輪廓得到文字區域資訊
首先,圖片通過特征金字塔結構的backbone,通過上采樣的方式將特征金字塔的輸出變換為同一尺寸,并級聯(cascade)產生特征F;然后,通過特征圖F預測概率圖(P — probability_map)和閾值圖(T — threshold_map); 最后,通過概率圖P和閾值圖T生成近似的二值圖(B — approximate_binary_map),
在訓練階段,監督被應用在閾值圖、概率圖和近似的二值圖上,其中后兩者共享同一個監督;在推理階段,則可以從后兩者輕松獲取邊界框,
可微的二值化(Differentiable binarization)
傳統的閾值分割做法為:

$\ B_{i,j} $ 代表了probability_map中第i行第j列的概率值,這樣的做法是硬性將概率大于某個固定閾值的像素作為文字像素,而不能將閾值作為一個可學習的引數物件(因為閾值分割沒辦法微分進行梯度回傳)
可微分的二值化公式:

首先,該公式借鑒了sigmod函式的形式(sigmod 函式本身就是將輸入映射到0~1之間),所以將概率值 $\ P_{i,j} $ 與閾值 $\ T_{i,j} $ 之間的差值作為sigmod函式的輸出,然后再經過放大系數 \(k\), 將其輸出無限逼近兩個極端 0 或者1;其中,k為放大因子,依經驗設定為 50
帶有自適應閾值的可微分二值化不僅有助于把文字區域與背景區分開,而且還能把相近的實體分離開來,

我們來根據label generation中的gt 與 threshold_map來分別計算下,經過這個可微分二值化的sigmod函式后,各個區域的像素值會變成什么樣子:
文字實體中心區域像素:
- probability map 的gt為 1
- threshold map的gt值為0.3

如果不經過放大系數K的放大,那么區域正中心的像素如上圖所示經過sigmod函式后趨向于0.6左右的值,但是經過放大系數k后,會往右傾向于1,
文字實體邊緣區域像素:
- probability map 的gt為 1
- threshold map的gt值為0.7

如果不經過放大系數K的放大,那么區域正中心的像素如上圖所示經過sigmod函式后趨向于0.5左右的值,但是經過放大系數k后,會往右傾向于1,
文字實體外的像素:
- probability map 的gt為 0
- threshold map的gt值為0.3

經過放大系數k后,激活值會無限趨近于0; 從而實作二值化效果,
解釋了DB利用類似sigmod的函式是如何實作二值化的效果,那么我們來看其梯度的學習性:
傳統二值化是一個分段函式,如下圖所示:

SB:standard binarization其梯度在0值被截斷無法進行有效地回傳, DB:differentiable binarization是一個可微分的曲線,可以利用訓練資料+優化器的形式進行資料驅動的學習優化,
我們來看其導數公式,假設 \(l_+\) 代表了正樣本, \(l_-\) 代表了負樣本,則:

根據鏈式法則我們可以計算其loss梯度
百度paddle中提供的介面可以實作下面的效果:


轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/552123.html
標籤:其他
下一篇:返回列表
