那些做OCR要踩的坑

原本這篇單純只是在前前公司(金融)和前公司(電信)時,花了不少時間處理這塊
用PPOCRLabel來幫PaddleOCR做OCR的微調和標註
後來因為多模態模型越來越勵害,所以這塊就有點放生;但意外發現最近冒出很多相關的開源,所以動手稍微 (當然可能有漏掉的) 整理 (實際做過) 一下 (PaddleOCR的部份在比較下方),其中
  • MinerU、markitdown 是功能強大的文檔轉換工具,適用於處理各種文件格式。
  • GOT-OCR 2.0、olmocr、docling 就是 OCR 模型,從圖像和 PDF 中提取文本。
  • Phi-4-multimodal-instruct、MiniCPM-o 則是多模態,可以處理不同類型數據。
基本上安裝都變得不難了,官方 github 都有寫,甚至有 huggingface demo 所以就不多班門弄斧了

儲存庫 優點 缺點 適用場景
MinerU
(DEMO)
整合 OCR 與數據分析,適合企業數據提取,支持 84 種語言 非純 OCR 工具,可能對 OCR 深度調優有限 企業級數據挖掘與文字提取
markitdown 自動轉換 Markdown,提升文檔可讀性,支持多種文件格式 命令列和 Python API 使用 OCR 功能可能較弱 將文檔轉為 Markdown 用於自動化文檔生成
llm_aided_oc LLM 輔助 OCR,提高準確度 計算資源需求較大 高準確性需求的困難文檔處理
GOT-OCR2.0
(DEMO)
強大 OCR 模型,針對文本識別優化 多模態處理能力有限 純 OCR 任務,如掃描文檔轉換
olmocr
(DEMO)
可能針對特定領域優化支持使用 Sglang 處理數百萬個 PDF 缺乏完整資訊,難以評估 針對特定語言或格式的 OCR
docling 進階文檔分析與處理包括頁面佈局、閱讀順序、表格結構、代碼、公式和圖像分類 提供多種導出格式和選項,包括 Markdown、HTML 和無損 JSON 非純 OCR 專精 需要 OCR 與文檔分析結合的應用
Phi-4-multimodal-instruct 能處理多模態輸入,如圖表解析 簡單 OCR 任務可能過於複雜 圖表解讀、混合文字與影像資訊處理
MiniCPM-o 輕量化,適用移動端與低資源設備 可能在高準確度 OCR 上有所妥協 移動設備上的即時 OCR

olmocr:安裝很快,官方 github 都有說明
sudo apt-get update && apt-get install poppler-utils ttf-mscorefonts-installer msttcorefonts fonts-crosextra-caladea fonts-crosextra-carlito gsfonts lcdf-typetools

conda create -n olmocr python=3.11 -y && conda activate olmocr

git clone https://github.com/allenai/olmocr.git 
cd olmocr 
pip install -e .

pip install gradio pandas
pip install sgl-kernel==0.0.3.post1 --force-reinstall --no-deps
pip install "sglang[all]==0.4.2" --find-links https://flashinfer.ai/whl/cu124/torch2.4/flashinfer/ 

python -m olmocr.pipeline ./localworkspace --pdfs tests/gnarly_pdfs/horribleocr.pdf
./localworkspace:指定工作空間目錄,用於存放中間文件和最終結果。 
--pdfs:指定要處理的 PDF 路徑(例如 tests/gnarly_pdfs/horribleocr.pdf 是倉庫中的測試文件)。 
您可以將 tests/gnarly_pdfs/horribleocr.pdf 替換為您自己的 PDF 文件路徑。
完成後,結果會以 JSON 格式存儲在 ./localworkspace 目錄下。
提取的文字會以 Dolma 風格的 JSONL 格式存儲在 ./localworkspace/results 子目錄

Recent NVIDIA GPU (tested on RTX 4090, L40S, A100, H100) with at least 20 GB of GPU RAM

PS: 中間可能碰到 "Attempt 1: All connection attempts failed" 照官方作法,裝到olmocr-0.1.59應該正常
再自己想辦法把它做成 API 以及做個 gradio 那就可以玩啦 !

2023/08 公司添購 RTX 6000 Ada 48 GB * 2 和 A 100 80GB * 4
2024/05 公司添購RTX 6000 Ada 48 GB * 8 * 2

這邊則是體驗一下用多模態的校槨

Paddle OCR 應用場景開發微調 (官方github FAQ)
雖然這篇是在講 OCR,但多模態的大模型好像應該也得略懂 XD 所以試了一下地端佈署、Prompt、function call 再到workflow;畢竟想要讓OCR更準一點,如果有多模態協助,那效果還是挺不錯的啊 !

目前現有 PP-OCR系列模型列表:推理、訓練、預訓練,然後檢測跟識別;官方文件如下:
快速安裝:本來想用官方放的 docker,但是 root,然後改不太動,最後乾脆用自己的docker

首先就是識別,說明一下字典檔相關數據的生成,為了輸出的效果更符合目前優先的醫療收據應用場景,所以根據已搜集的7萬筆醫囑還有台灣常用字典檔做為語料庫,藉此產生大量的數據資料,來微調 ppocr-v3;這邊要怎樣生成呢 ? 可以參考 文字資料集產生(text_renderer)  或者是你前面有用 PPOCRLabelv2 標了一些數據,那麼就可以把標好的文字拿來再做數據集生成的組合。

PS: 感謝曾一起合作的幾個小夥伴們辛苦標註
如果有整個先把前面附上的官網github連結看完,會發現在模型微調那頁有個最重要的說明:"在自己的場景中,透過模型變化,可以取得精確度較高的文字偵測與辨識模型。"以及強調了這句:"加入少量真實資料(偵測任務>=500張,辨識任務>=5000張),會大幅提升類別場景的偵測與辨識效果。"同時關於偵測模型的訓練也又說 " 選擇PP-OCRv3模型(配置:ch_PP-OCRv3_det_student.yml,預訓練模型:ch_PP-OCRv3_det_distill_train.tar)進行拓展,其精度和泛化性能是目前提供的最優化預訓練模型。" 識別模型也不例外說了 "選擇PP-OCRv3模型(設定檔:ch_PP-OCRv3_rec_distillation.yml,預訓練模型:ch_PP-OCRv3_rec_train.tar),其精確度與泛化效能是目前提供的最優預訓練模型。"個人另外發現,若是跑在 docker裡,來不及修改共享記記憶體時,可以在config裡的 data 的 loader 處補上這行 " use_shared_memory: False " 所以我的偵測和識別的訓練指令分別如下:
 
python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c /opt/data/PaddleOCR/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Global.pretrained_model=/opt/data/PaddleOCR/pretrain_models/ch_PP-OCRv3_det_distill_train/student.pdparams

python3 tools/infer_det.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Global.infer_img="/opt/data/Account-Documents/25-QR-Code/140_PXL_20240305_095734055.jpg" Global.pretrained_model="./output/ch_PP-OCR_V3_det/best_accuracy"

python3 tools/export_model.py -c /opt/data/PaddleOCR/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Global.pretrained_model="/opt/data/PaddleOCR/output/2024-05-21_ch_PP-OCR_V3_det/best_accuracy" Global.save_inference_dir="/opt/data/PaddleOCR/output/inference_2024-05-21_ch_PP-OCR_V3_det/"

python3 tools/infer/predict_det.py --det_algorithm="DB" --det_model_dir="/opt/data/PaddleOCR/output/inference_2024-05-21_ch_PP-OCR_V3_det/" --image_dir="/opt/data/PaddleOCR/inference_test/" --use_gpu=True
 
python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml -o Global.pretrained_model=./pretrain_models/20230803/best_accuracy

python3 tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml -o Global.pretrained_model=/opt/data/PaddleOCR/output/2024-05-26_ppocr_v3_rec_distillation/best_accuracy Global.save_inference_dir=/opt/data/PaddleOCR/output/inference_2024-05-26_ppocr_v3_rec_distillation/
 
python3 tools/infer/predict_system.py --image_dir="./inference_test/" --det_model_dir="./output/inference_2024-05-21_ch_PP-OCR_V3_det/" --rec_model_dir="./output/inference_2024-05-26_ppocr_v3_rec_distillation/Student/" --use_angle_cls=false --use_mp=True --total_process_num=4 --rec_char_dict_path="./configs/rec/PP-OCRv3/zhtw_common_dict.txt"

最後在V100*8的機器上費時51hr跑了100epoch,訓練acc: 0.84133,驗證acc:0.92796
來個 PaddleOCR 的 識別(REC) 訓練擷圖 ! 2023/07/15訓練集有100萬張,驗證集有1萬張。
這邊要加減補充一下 !!! 整個 PaddleOCR 就是分為 Detection (偵測,ch_PP-OCRv3_det) 跟 Recognition (識別,ch_PP-OCRv3_rec),其中,偵測又有所謂的表格,但就是要先處理識別,因為都只有簡體字 ! 經過一番實測,用 ch_PP-OCRv3_rec 並且將字典檔轉成繁體,且要注意因為字典檔內有些許繁體字,直接簡轉繁會造成重複,所以替換時要小心
最後就是到了把整個模型佈到 HuggingFace Hub 上了,像是

想用 python 直接調用自定義數據的訓練模型,但是看log最後都會變為使用官方預訓練模型 (會出現如 det=True, rec=True, type=ocr 等等,並另外本地端執行自定義數據訓練和官方預訓練模型確認是官方預訓練模型結果)。使用自訂模型

ocr = PaddleOCR(det_model_dir='{your_det_model_dir}', rec_model_dir='{your_rec_model_dir}', rec_char_dict_path='{your_rec_char_dict_path}', cls_model_dir='{your_cls_model_dir}', use_angle_cls=True)
result = ocr.ocr(img, cls=True, det=False, rec=False)

載入模型的時候報以下錯誤: ./pretrain_models/MobileNetV3_large_x0_5_pretrained/.pdparams not found, 可以參考這邊修改:下載預訓練模型

最後可以看一下這邊是怎樣計算你的模型訓練效果

WSL 安裝 PPOCRLabel。一切都是從這個神奇的需求開始的,因為要識別醫療診斷書中的醫囑內容,所以前期處理的OCR識別就非常重要,雖然 PaddleOCR (https://github.com/PaddlePaddle/PaddleOCR) 已經很強,但是卡在很多格式內容或者簡體和繁體字的問題,所以常常OCR識別後的內容就出包,然後導致醫囑的分析也就容易跟著翻車啦 (但BU端才不管你這些呢 >"<);所以只能再次抱著壯士斷腕的決心,再自己標註一次數據了 ! 那麼,值得一提的是,標註NLP的工具可以用標文字蠻不錯的 Doccano (https://github.com/doccano/doccano) 或者是可以標圖像和文字的 Label Studio (https://labelstud.io/),但是要標給OCR用,感覺上還是得用 PPOCRLabelv2但因為平常不太可能開著 Ubuntu 來工作,所以只能想辦法從 WINDOWS 10 上安裝 WSL (1或2),然後再幫它啟用桌面,然後採遠端桌面登入,接著再來安裝中文輸入法等等;總計有這幾個動作:

  • WINDOWS 10 啟用 WSL
  • WSL 啟動 Ubuntu 再啟用桌面
  • WINDOWS 10 遠端桌面至 WSL 的 Ubuntu
  • 安裝 PaddleOCR、PPOCRLabelv2 
  • 幫 WSL 的 Ubuntu 安裝繁體中文輸入法
但還是加減把 PaddleOCR 的應用場景開發過程,WINDOWS 10 安裝 PaddleOCR、PPOCRLabelv2 的一堆奇怪的問題記錄,參考文件都記錄下來吧

WINDOWS 10 啟用 WSL

先啟用 WSL 1 或 2,目前已知就是差在要怎樣直接遠端桌面,或者是透過 XLaunch來連線;我目前是啟用 WSL 2 ! 所以裝好後就是到 Microsoft 商店取得 Ubuntu 22.04.2 LTS (在上面的連結) 啦 ! 照官網所寫,其實安裝跟啟動非常簡單,然後就是設定帳號跟密碼,主要是給你能使用 sudo 這樣 ! 網上有的教學說要再另外裝 terminal,但我裝好是直接有個 Ubuntu 22.04.2 的終端機可以啟動啦 ! 

$ sudo apt update && sudo apt upgrade
$ sudo apt install -y xfce4 xrdp xfce4-goodies

再來就是要更新還有安裝遠端桌面和繁體中文輸入法所需套件,安裝xfce4過程中會出現選擇顯示管理DM選擇的提示,建議用lightdm。

$ sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
$ sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini
$ sudo sed -i 's/max_bpp=32/#max_bpp=32\nmax_bpp=128/g' /etc/xrdp/xrdp.ini
$ sudo sed -i 's/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g' /etc/xrdp/xrdp.ini
$ echo xfce4-session > ~/.xsession
修改 xrdp 設定,並註解掉 X11 那兩行
$ sudo vi /etc/xrdp/startwm.sh
# test -x /etc/X11/Xsession && exec /etc/X11/Xsession
# exec /bin/sh /etc/X11/Xsession
然後新增 xfce 這兩行
# xfce
startxfce4
接著就是啟動 RDP 然後看狀態
$ sudo /etc/init.d/xrdp start
$ sudo /etc/init.d/xrdp status
* xrdp-sesman is running
* xrdp is running
接著就是安裝Fctix5設定新酷音輸入法;其中,別忘了要到設定裡的地區和語言設定語言支援,不過不知為啥,我的是沒辦法設定,但是卻有直接一個 Fctix5 的選項,點一點就這樣意外搞定?
$ sudo apt install fcitx5 fcitx5-chinese-addons fcitx5-config-qt fcitx5-chewing
以上就是在Windows 10 跑 WSL 2,然後設定遠端桌面跟注音輸入法(繁體),陸續參考了以下文章

接著就是安裝 PaddleOCR 還有 PPOCRLabelv2,每次在做這些工作時,總會想到為何那麼多人在抗中保台,結果放眼望去,台灣都沒相關的數據或者工具套件開源出來?XD

https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.6/PPOCRLabel/README_ch.md

https://zhuanlan.zhihu.com/p/523972865
PPv3-OCR自定義數據從訓練到部署

然後這時發現其實可以省掉上面的 WSL,直接裝 WINDOWS 版就可以了 XD
所以最後就補充一些碰到的問題,然後分別參考了那些連結解決的吧
最後 ! 附上一個PPOCRLabelv2標註的擷圖