摘要:本案例我們利用影片字幕識別中的文字檢測與識別模型,增加預訓練Bert進行糾錯
本文分享自華為雲社群《Bert特調OCR》,作者:杜甫蓋房子。
做這個專案的初衷是發現圖比較糊/檢測框比較長的時候,OCR會有一些錯誤識別,所以想對識別結果進行糾錯。一個很自然的想法是利用語義資訊進行糾錯,其實在OCR訓練時加入語義資訊也有不少工作,感興趣的朋友可以瞭解一下,為了更大程度複用已有的專案,我們決定保留現有OCR單元,在之後加入獨立語義糾錯模組進行糾錯。
本案例我們利用影片字幕識別中的文字檢測與識別模型,增加預訓練Bert進行糾錯,最終效果如下:
我們使用ModelBox Windows SDK
進行開發,如果還沒有安裝SDK
,可以參考ModelBox端雲協同AI開發套件(Windows)裝置註冊篇、ModelBox端雲協同AI開發套件(Windows)SDK安裝篇完成裝置註冊與SDK
安裝。
技能開發
這個應用對應的ModelBox
版本已經做成模板放在華為雲OBS中,可以用sdk中的solution.bat
工具下載,接下來我們給出該應用在ModelBox
中的完整開發過程:
1)下載模板
執行.\solution.bat -l
可看到當前公開的技能模板:
███@DESKTOP-UUVFMTP MINGW64 /d/DEMO/modelbox-win10-x64-1.5.1 $ ./solution.bat -l start download desc.json 3942.12KB/S, percent=100.00% Solutions name: mask_det_yolo3 ... doc_ocr_db_crnn_bert
結果中的doc_ocr_db_crnn_bert即為文件識別應用模板,下載模板:
███@DESKTOP-UUVFMTP MINGW64 /d/DEMO/modelbox-win10-x64-1.5.1 $ ./solution.bat -s doc_ocr_db_crnn_bert ...
solution.bat
工具的引數中,-l
代表list
,即列出當前已有的模板名稱;-s
代表solution-name
,即下載對應名稱的模板。下載下來的模板資源,將存放在ModelBox
核心庫的solution
目錄下。
2)建立工程
在ModelBox
sdk目錄下使用create.bat
建立doc_ocr
工程
███@DESKTOP-UUVFMTP MINGW64 /d/DEMO/modelbox-win10-x64-1.5.1 $ ./create.bat -t server -n doc_ocr -s doc_ocr_db_crnn_bert sdk version is modelbox-win10-x64-1.5.1 success: create doc_ocr in D:\DEMO\modelbox-win10-x64-1.5.1\workspace
create.bat
工具的引數中,-t
表示建立事務的類別,包括工程(server)、Python功能單元(Python)、推理功能單元(infer)等;-n
代表name
,即建立事務的名稱;-s
代表solution-name
,表示將使用後面引數值代表的模板建立工程,而不是建立空的工程。
workspace
目錄下將建立出doc_ocr
工程,工程內容如下所示:
doc_ocr |--bin │ |--main.bat:應用執行入口 │ |--mock_task.toml:應用在本地執行時的輸入輸出配置,此應用為http服務 |--CMake:存放一些自定義CMake函式 |--data:存放應用執行所需要的圖片、影片、文字、配置等資料 │ |--char_meta.txt:字形拆解檔案,用來計算字形相似度 │ |--character_keys.txt:OCR演算法的字符集合 │ |--GB2312.ttf:中文字型檔案 │ |--test_http.py:應用測試指令碼 │ |--text.jpg:應用測試圖片 │ |--vocab.txt:tokenizer配置檔案 |--dependence │ |--modelbox_requirements.txt:應用執行依賴的外部庫在此檔案定義,本應用依賴pyclipper、Shapely、pillow等工具包 |--etc │ |--flowunit:應用所需的功能單元存放在此目錄 │ │ |--cpp:存放C++功能單元編譯後的動態連結庫,此應用沒有C++功能單元 │ │ |--bert_preprocess:bert預處理功能單元,條件功能單元,判斷是否需要糾錯 │ │ |--collapse_position:歸攏單句糾錯結果 │ │ |--collapse_sentence:歸攏全文糾錯結果 │ │ |--det_post:文字檢測後處理功能單元 │ │ |--draw_ocr:ocr結果繪製功能單元 │ │ |--expand_img:展開功能單元,展開文字檢測結果 │ │ |--expand_position:展開功能單元,展開bert預處理結果 │ │ |--match_position:匹配糾錯結果 │ │ |--ocr_post:ocr後處理功能單元 |--flowunit_cpp:存放C++功能單元的原始碼,此應用沒有C++功能單元 |--graph:存放流程圖 │ |--doc_ocr.toml:預設流程圖,http服務 │ |--modelbox.conf:modelbox相關配置 |--hilens_data_dir:存放應用輸出的結果檔案、日誌、效能統計資訊 |--model:推理功能單元目錄 │ |--bert:Bert推理功能能單元 │ │ |--bert.toml:語義推理配置檔案 │ │ |--bert.onnx:語義推理模型 │ |--det:文字檢測推理功能單元 │ │ |--det.toml:文字檢測推理功能單元的配置檔案 │ │ |--det.onnx:文字檢測onnx模型 │ |--ocr:文字識別推理功能單元 │ │ |--ocr.toml:文字識別推理功能單元的配置檔案 │ │ |--ocr.onnx:文字識別onnx模型 |--build_project.sh:應用構建指令碼 |--CMakeLists.txt |--rpm:打包rpm時生成的目錄,將存放rpm包所需資料 |--rpm_copyothers.sh:rpm打包時的輔助指令碼
3)檢視流程圖
doc_ocr
工程graph
目錄下存放流程圖,預設的流程圖doc_ocr.toml
與工程同名,將流程圖視覺化:
圖示中,灰色部分為預置功能單元,其餘顏色為我們實現的功能單元,其中綠色為一般通用功能單元,紅色為推理功能單元,藍色為條件功能單元,黃色為展開歸攏功能單元。HTTP接收圖解碼後做預處理,接著是文字檢測,模型後處理得到檢測框,經過條件功能判斷,檢測到文字的圖送入展開功能單元,切圖進行文字識別,文字識別結果送入bert預處理單元判斷是否需要進行糾錯,如需糾錯則再展開並行進行語義推理,不需要糾錯的就直接進行結果繪製並返回。而未檢測到文字的幀則直接返回。
4)核心邏輯
本應用核心邏輯中的文字檢測與識別可以參考【ModelBox OCR實戰營】影片字幕識別中的相關介紹,本文重點介紹文字糾錯部分。
首先檢視糾錯預處理功能單元bert_preprocess
:
def process(self, data_context): in_feat = data_context.input("in_feat") out_feat = data_context.output("out_feat") out_bert = data_context.output("out_bert") for buffer_feat in in_feat: ocr_data = json.loads(buffer_feat.as_object())['ocr_result'] score_data = json.loads(json.loads(buffer_feat.as_object())['result_score']) text_to_process = [] text_to_pass = [] err_positions = [] for i, (sent, p) in enumerate(zip(ocr_data, score_data)): if not do_correct_filter(sent, self.max_seq_length): text_to_pass.append((i, sent)) else: err_pos = find_err_pos_by_prob(p, self.prob_threshold) if not err_pos: text_to_pass.append((i, sent)) else: text_to_process.append(sent) err_positions.append(err_pos) if not text_to_process: out_feat.push_back(buffer_feat) else: out_dict = [] texts_numfree = [self.number.sub(lambda m: self.rep[re.escape(m.group(0))], s) for s in text_to_process] err_positions = check_error_positions(texts_numfree, err_positions) if err_positions is None: err_positions = [range(len(d)) for d in texts_numfree] batch_data = BatchData(texts_numfree, err_positions, self.tokenizer, self.max_seq_length) input_ids, input_mask, segment_ids, masked_lm_positions = batch_data.data ... return modelbox.Status.StatusCode.STATUS_SUCCESS
預處理單元對透過do_correct_filter
函式對OCR結果進行判斷,只對大於3個字的中文字元進行糾錯:
def do_correct_filter(text, max_seq_length): if re.search(re.compile(r'[a-zA-ZA-Za-z]'), text): return False if len(re.findall(re.compile(r'[\u4E00-\u9FA5]'), text)) < 3: return False if len(text) > max_seq_length - 2: return False return True
透過find_err_pos_by_prob
函式定位需要糾錯的字元,只對OCR置信度小於閾值的字元進行糾錯:
def find_err_pos_by_prob(prob, prob_threshold): if not prob: return [] err_pos = [i for i, p in enumerate(prob) if p < prob_threshold] return err_pos
如有需要糾錯的字元,則將該句編碼,進行語義推理。
語義推理後,透過collapse_position
對推理結果進行解碼,在match_position
功能單元中使用shape_similarity
函式計算語義推理結果與OCR結果的字元相似度:
def shape_similarity(self, char1, char2): decomp1 = self.decompose_text(char1) decomp2 = self.decompose_text(char2) similarity = 0.0 ed = edit_distance(safe_encode_string(decomp1), safe_encode_string(decomp2)) normalized_ed = ed / max(len(decomp1), len(decomp2), 1) similarity = max(similarity, 1 - normalized_ed) return similarity
其中,decompose_text函式將單個漢字編碼為筆劃級別的IDS,如:
華: ⿱⿰⿰丿丨⿻乚丿⿻一丨
華 +----+ | ⿱ | +----+ 化 十 +----+ +----+ | ⿰ | | ⿻ | +----+ +----+ 亻 七 一 丨 +----+ +----+ | ⿰ | | ⿻ | +----+ +----+ 丿 丨 乚 丿
計算語義推理結果字元與原OCR結果字元相似度之後,綜合語義推理置信度與相似度判斷是否接收糾錯結果:
def accept_correct(self, confidence, similarity): if confidence + similarity >= self.all_conf \ and confidence >= self.confidence_conf \ and similarity >= self.similarity_conf: return True return False
5)三方依賴庫
本應用依賴pyclipper、Shapely、pillow等工具包,ModelBox應用不需要手動安裝三方依賴庫,只需要配置在dependence\modelbox_requirements.txt
,應用在編譯時會自動安裝。
技能執行
在專案目錄下執行.\bin\main.bat
執行應用,為了方便觀察糾錯結果,我們將日誌切換為info:
███@DESKTOP-UUVFMTP MINGW64 /d/DEMO/modelbox-win10-x64-1.5.1/workspace/doc_ocr $ ./bin/main.bat default info ... [2022-12-27 15:20:40,043][ INFO][httpserver_sync_receive.cc:188 ] Start server at http://0.0.0.0:8083/v1/ocr_bert
另起終端,進入專案data
目錄下,執行test_http.py
指令碼進行測試:
███@DESKTOP-UUVFMTP MINGW64 /d/DEMO/modelbox-win10-x64-1.5.1/workspace/doc_ocr/data $ python test_http.py
可以在技能執行日誌中觀察到接受的糾錯結果:
[2022-12-27 15:22:40,700][ INFO][match_position\match_position.py:51 ] confidence: 0.99831665, similarity: 0.6470588235294117, 櫃 -> 相
同時,在data
目錄下可以看到應用返回的結果圖片: