關注,回復python,獲取80G免費python實戰文檔和視頻資料!
摘要:本文由以數據之名分享。人工智慧在左,應用場景在右;圖像識別在前,OCR識別在後。今天,讓我們跟隨著小編的節奏,首先了解下OCR技術的前世今生,其次手把手知會你部署OCR依賴環境,最後5分鐘搞定自己的專屬OCR識別服務API。
1.1、OCR的應用場景根據OCR的應用場景而言,我們可以大致分成識別特定場景下的專用OCR和識別多種場景下的通用OCR。就前者而言,證件識別以及車牌識別就是專用OCR的典型案例。針對特定場景進行設計、優化以達到最好的特定場景下的效果展示。那通用的OCR就是使用在更多、更複雜的場景下,擁有比較好的泛性。
在這個過程中由於場景的不確定性,比如:圖片背景極其豐富、亮度不均衡、光照不均衡、殘缺遮擋、文字扭曲、字體多樣等等問題,會帶來極大的挑戰。而目前PaddleHub為大家提供的是超輕量級中文OCR模型,聚焦特定的場景,支持中英文數字組合式識別、豎排文字識別、長文本識別場景。
1.2、OCR的技術路線OCR,即學字符識別(Optical Character Recognition),是指對文本資料的圖像文件進行分析識別處理、獲取文字及版面信息的過程。亦即將圖像中的文字進行識別,並以文本的形式返回。
OCR的基本流程可以簡單分為以下幾步:
1. 輸入:
不同的圖像格式有不同的存儲、壓縮方式,目前有OpenCV、CxImage等。
2. 二值化:
如今數碼攝像頭拍攝的圖片大多是彩色圖像,彩色圖像所含信息量巨大,不適用於OCR技術。為了讓計算機更快的、更好地進行OCR相關計算,我們需要先對彩色圖進行處理,使圖片只剩下前景信息與背景信息。二值化也可以簡單地將其理解為「黑白化」。
3. 圖像降噪:
對於不同的圖像根據噪點的特徵進行去噪的過程稱為降噪。
4. 傾斜校正:
由於一般用戶,在拍照文檔時,難以拍攝得完全符合水平平齊與豎直平齊(我本人就經常拍的歪歪扭扭),因此拍照出來的圖片不可避免的產生傾斜,這就需要圖像處理軟體進行校正。
5. 版面分析:
將文檔圖片分段落,分行的過程稱為版面分析
6. 字符切割:
由於拍照、書寫條件的限制,經常造成字符粘連、斷筆,直接使用此類圖像進行OCR分析將會極大限制OCR性能。因此需要進行字符切割,即:將不同字符之間分割開。
7. 字符識別:
早期以模板匹配為主,後期以結合深度網絡的特徵提取為主。版面還原:將識別後的文字像原始文檔圖片那樣排列,段落、位置、順序不變地輸出到Word文檔、PDF文檔等,這一過程稱為版面還原。
8. 後期處理:
根據特定的語言上下文的關係,對識別結果進行校正。
9. 輸出:
將識別出的字符以某一格式的文本輸出。
以上9步也可以簡單總結,典型的OCR技術路線如下圖所示:
其中OCR識別的關鍵路徑在於文字檢測和文本識別部分,這也是深度學習技術可以充分發揮功效的地方。PaddleHub為大家開源的預訓練模型的網絡結構是Differentiable Binarization+ CRNN,基於icdar2015數據集下進行的訓練。
首先,DB是一種基於分割的文本檢測算法。在各種文本檢測算法中,基於分割的檢測算法可以更好地處理彎曲等不規則形狀文本,因此往往能取得更好的檢測效果。但分割法後處理步驟中將分割結果轉化為檢測框的流程複雜,耗時嚴重。因此作者提出一個可微的二值化模塊(Differentiable Binarization,簡稱DB),將二值化閾值加入訓練中學習,可以獲得更準確的檢測邊界,從而簡化後處理流程。DB算法最終在5個數據集上達到了state-of-art的效果和性能。參考論文:Real-time Scene Text Detection with Differentiable Binarization
下圖是DB算法的結構圖:
接著,我們使用 CRNN(Convolutional Recurrent Neural Network)即卷積遞歸神經網絡,是DCNN和RNN的組合,專門用於識別圖像中的序列式對象。與CTC loss配合使用,進行文字識別,可以直接從文本詞級或行級的標註中學習,不需要詳細的字符級的標註。參考論文:An end-to-end trainable neural network for image-based sequence recognition and its application to scene text recognition
下圖是CRNN的網絡結構圖:
飛槳首次開源文字識別模型套件PaddleOCR,目標是打造豐富、領先、實用的文本識別模型/工具庫。最新開源的超輕量ppocr_mobile移動端系列:檢測(2.6M)+方向分類器(0.9M)+ 識別(4.6M)= 8.1M。同時支持中英文識別;支持傾斜、豎排等多種方向文字識別;在測試數據單圖平均17個檢測框條件下,T4單次預測全程平均耗時僅137ms;支持GPU、CPU預測;用戶既可以通過PaddleHub很便捷的直接使用該超輕量模型,也可以使用PaddleOCR開源套件訓練自己的超輕量模型。
1.4、PaddleHub 模型介紹類別:圖像 - 文字識別
網絡:Differentiable Binarization+CRNN
數據集:icdar2015數據集
模型概述:
chinese_ocr_db_crnn_server Module用於識別圖片當中的漢字。其基於chinese_text_detection_db_server檢測得到的文本框,繼續識別文本框中的中文文字。之後對檢測文本框進行角度分類。最終識別文字算法採用CRNN(Convolutional Recurrent Neural Network)即卷積遞歸神經網絡。其是DCNN和RNN的組合,專門用於識別圖像中的序列式對象。與CTC loss配合使用,進行文字識別,可以直接從文本詞級或行級的標註中學習,不需要詳細的字符級的標註。該Module是一個通用的OCR模型,支持直接預測。
類別:圖像 - 文字識別
網絡:Differentiable Binarization+CRNN
數據集:icdar2015數據集
模型概述:
chinese_ocr_db_crnn_mobile Module用於識別圖片當中的漢字。其基於[chinese_text_detection_db_mobile Module](https://www.paddlepaddle.org.cn/hubdetail?name=chinese_text_detection_db_mobile&en_category=TextRecognition)檢測得到的文本框,繼續識別文本框中的中文文字。之後對檢測文本框進行角度分類。最終識別文字算法採用CRNN(Convolutional Recurrent Neural Network)即卷積遞歸神經網絡。其是DCNN和RNN的組合,專門用於識別圖像中的序列式對象。與CTC loss配合使用,進行文字識別,可以直接從文本詞級或行級的標註中學習,不需要詳細的字符級的標註。該Module是一個超輕量級中文OCR模型,支持直接預測。
https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2020.11-Windows-x86_64.exe
下載完成後,雙擊安裝程序進入圖形界面
默認安裝位置為C盤,建議將安裝位置更改到D盤:
# 在命令行輸入以下命令,創建名為paddleocr_env的環境
# 此處為加速下載,使用清華源
conda create --name paddleocr_env python=3.8 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
3.1、創建anaconda環境
conda create --name paddleocr_env python=3.8 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
3.2、激活conda paddle_env環境conda activate paddleocr_env3.3、查看當前python的位置
4.1、部署PaddlePaddle
python3 -m pip install paddlepaddle-gpu -i https:或pip install paddlepaddle-gpu -i https:python3 -m pip install paddlepaddle -i https:或pip install paddlepaddle -i https:4.2、PaddlePaddle驗證
PaddlePaddle安裝完成後,您可以使用 python 進入python解釋器,
python
import paddle paddle.utils.run_check()出現PaddlePaddle is installed successfully!,說明您已成功安裝。
5.1、部署PaddleOCR whl包
pip3 install "paddleocr>=2.3"
5.2、本地部署PaddleOCR包
cd PaddleOCRpip3 install -r requirements.txt
ERROR: Failed building wheel for python-Levenshtein
Running setup.py clean for python-Levenshtein
下載python-levenshtein,https://www.lfd.uci.edu/~gohlke/pythonlibs/#python-levenshtein,
pip install python-Levenshtein "d:\minjie.qu\桌面\processon\文檔\ML\python_Levenshtein-0.12.2-cp38-cp38-win_amd64.whl"
5.3、PaddleOCR部署驗證PaddleOCR安裝完成後,您可以使用 python 進入python解釋器,
python
from paddleocr import PaddleOCR, draw_ocr
FileNotFoundError: Could not find module 'D:\Software\Anaconda3\envs\paddleocr_env\Library\bin\geos_c.dll' (or one of its dependencies). Try using the full path with constructor syntax.
下載shapely,https://www.lfd.uci.edu/~gohlke/pythonlibs/#shapely,對應文件為Shapely‑1.7.1‑cp38‑cp38‑win_amd64.whl。
解壓縮shapely文件,找到.\Shapely-1.7.1-cp38-cp38-win_amd64.whl\shapely\DLLs\geos_c.dll文件
複製文件到對應acoda環境目錄,.\Anaconda3\envs\paddleocr_env\Library\bin
再次驗證PaddleOCR安裝,使用 python 進入python解釋器。執行腳本:from paddleocr import PaddleOCR, draw_ocr。驗證異常
ModuleNotFoundError: No module named 'pyclipper'
手動安裝,
再次驗證PaddleOCR安裝,使用 python 進入python解釋器。執行腳本:from paddleocr import PaddleOCR, draw_ocr。驗證異常
ModuleNotFoundError: No module named 'imgaug'
手動安裝,
為了規避其他依賴包部署問題,手動執行下6步驟,再次遠程部署下PaddleOCR包。如下圖,部署成功。
再次驗證PaddleOCR安裝,使用 python 進入python解釋器。執行腳本:
from paddleocr import PaddleOCR, draw_ocr驗證OK
6.1、下載原始測試圖片集
PaddleOCR提供了一系列測試圖片,可到paddleocr官方測試圖片集地址https://paddleocr.bj.bcebos.com/dygraph_v2.1/ppocr_img.zip下載並解壓,然後在終端中切換到相應目錄。
6.2、執行測試代碼切換至圖片目錄,cd ./ML/ppocr_img,執行python,進入python解釋器,執行如下代碼:
"""Spyder Editor
This is a temporary script file.@author 以數據之名@createTime 2021-09-14 10:20:00"""
from paddleocr import PaddleOCR, draw_ocr
def ocr_interface(img_path,language): "列印任何傳入的字符串" print(img_path,language) ocr = PaddleOCR(use_angle_cls=True,use_gpu=False, lang=language) result = ocr.ocr(img_path, cls=True) return result
ocr = PaddleOCR(use_angle_cls=True,use_gpu=False, lang="ch") img_path = './imgs/00056221.jpg'result = ocr.ocr(img_path, cls=True)for line in result: print(line)
from PIL import Image
image = Image.open(img_path).convert('RGB')boxes = [line[0] for line in result]txts = [line[1][0] for line in result]scores = [line[1][1] for line in result]im_show = draw_ocr(image, boxes, txts, scores, font_path='./fonts/simfang.ttf')im_show = Image.fromarray(im_show)im_show.save('result-train.jpg')6.3、測試識別結果
7.1、FastAPI特性
FastAPI 是一個現代、快速(高性能)的 Web 框架,用於基於標準 Python 類型提示使用 Python 3.6+ 構建 API。
主要特點是:
7.2、部署FastAPI
8.1、Uvicorn特性
Uvicorn是一個輕量級高效ASGI伺服器框架,是基於uvloop和httptools構建Python Web框架生態系統。
8.2、部署Uvicornpip install uvicorn[standard]8.3、uvicorn常用命令行
$ uvicorn --helpUsage: uvicorn [OPTIONS] APP
Options: --host TEXT Bind socket to this host. [default: 127.0.0.1] --port INTEGER Bind socket to this port. [default: 8000] --uds TEXT Bind to a UNIX domain socket. --fd INTEGER Bind to socket from this file descriptor. --reload Enable auto-reload. --reload-dir PATH Set reload directories explicitly, instead of using the current working directory. --reload-include TEXT Set glob patterns to include while watching for files. Includes '*.py' by default, which can be overridden in reload-excludes. --reload-exclude TEXT Set glob patterns to exclude while watching for files. Includes '.*, .py[cod], .sw.*, ~*' by default, which can be overridden in reload-excludes. --reload-delay FLOAT Delay between previous and next check if application needs to be. Defaults to 0.25s. [default: 0.25] --workers INTEGER Number of worker processes. Defaults to the $WEB_CONCURRENCY environment variable if available, or 1. Not valid with --reload. --loop [auto|asyncio|uvloop] Event loop implementation. [default: auto] --http [auto|h11|httptools] HTTP protocol implementation. [default: auto] --ws [auto|none|websockets|wsproto] WebSocket protocol implementation. [default: auto] --ws-max-size INTEGER WebSocket max size message in bytes [default: 16777216] --ws-ping-interval FLOAT WebSocket ping interval [default: 20.0] --ws-ping-timeout FLOAT WebSocket ping timeout [default: 20.0] --lifespan [auto|on|off] Lifespan implementation. [default: auto] --interface [auto|asgi3|asgi2|wsgi] Select ASGI3, ASGI2, or WSGI as the application interface. [default: auto] --env-file PATH Environment configuration file. --log-config PATH Logging configuration file. Supported formats: .ini, .json, .yaml. --log-level [critical|error|warning|info|debug|trace] Log level. [default: info] --access-log / --no-access-log Enable/Disable access log. --use-colors / --no-use-colors Enable/Disable colorized logging. --proxy-headers / --no-proxy-headers Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info. --server-header / --no-server-header Enable/Disable default Server header. --date-header / --no-date-header Enable/Disable default Date header. --forwarded-allow-ips TEXT Comma seperated list of IPs to trust with proxy headers. Defaults to the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'. --root-path TEXT Set the ASGI 'root_path' for applications submounted below a given URL path. --limit-concurrency INTEGER Maximum number of concurrent connections or tasks to allow, before issuing HTTP 503 responses. --backlog INTEGER Maximum number of connections to hold in backlog --limit-max-requests INTEGER Maximum number of requests to service before terminating the process. --timeout-keep-alive INTEGER Close Keep-Alive connections if no new data is received within this timeout. [default: 5] --ssl-keyfile TEXT SSL key file --ssl-certfile TEXT SSL certificate file --ssl-keyfile-password TEXT SSL keyfile password --ssl-version INTEGER SSL version to use (see stdlib ssl module's) [default: 17] --ssl-cert-reqs INTEGER Whether client certificate is required (see stdlib ssl module's) [default: 0] --ssl-ca-certs TEXT CA certificates file --ssl-ciphers TEXT Ciphers to use (see stdlib ssl module's) [default: TLSv1] --header TEXT Specify custom default HTTP response headers as a Name:Value pair --version Display the uvicorn version and exit. --app-dir TEXT Look for APP in the specified directory, by adding this to the PYTHONPATH. Defaults to the current working directory. [default: .] --factory Treat APP as an application factory, i.e. a () -> <ASGI app> callable. [default: False] --help Show this message and exit.8.4、部署文件上傳依賴插件pip install python-multipart
9.1、啟動API服務
uvicorn main:app --host 127.0.0.1 --port 8000 --reload9.2、接口文檔列表http://127.0.0.1:8000/ocrapi/docs#/9.3、APP主程序
"""Created on Sat Sep 18 10:56:10 2021
@author: 以數據之名@class:main"""
from typing import Optional,List
from fastapi import FastAPI, File, UploadFilefrom starlette.responses import HTMLResponsefrom pydantic import BaseModelfrom paddleocr_test import ocr_interface
from starlette.middleware import Middlewarefrom starlette.middleware.cors import CORSMiddleware
import uvicornimport jsonimport numpy as np
middleware = [ Middleware(CORSMiddleware, allow_origins=['*'])]
app = FastAPI(title= "OCR識別管理服務", description= "用於獲取圖片內容數據的接口", version= "1.0.0", openapi_url="/ocrapi/data_manger.json", docs_url="/ocrapi/docs", redoc_url="/ocrapi/redoc", middleware=middleware)
class Item(BaseModel): name: str price: float is_offer: Optional[bool] = None class Result(BaseModel): ronnum: int text: str = None confidence: float text_box_position: List[str] = []
"""@app.get("/")def read_root(): return {"Hello": "World"}"""
@app.get("/items/{item_id}")def read_item(item_id: int, q: Optional[str] = None): return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} @app.post("/file/")async def create_files(file: bytes = File(...)): with open('./base.jpg', 'wb') as f: f.write(file) return {"fileSize": len(file)} @app.post('/paddleocr/')async def paddleOCR(file: UploadFile = File(...)): """缺少驗證是否上傳文件""" content = await file.read() with open('./ocr_result/'+file.filename, 'wb') as f: f.write(content) result = ocr_interface('./ocr_result/'+file.filename,'ch') data = [] for i in range(len(result)): data.append({"rownum":i+1, "text":result[i][1][0], "confidence":result[i][1][1], "text_box_position":result[i][0]}) return {"filename": file.filename, "data":eval(json.dumps(data, ensure_ascii=False, cls=NumpyEncoder))} @app.post("/files/")async def create_files( files: List[bytes] = File(...)): print(type(files)) print(files) return {"file_sizes": [len(file) for file in files]} @app.post("/uploadfiles/")async def create_upload_files( files: List[UploadFile] = File(...)): return {"filenames": [file.filename for file in files]} @app.get("/")async def main(): content = """<body><form action="/paddleocr/" enctype="multipart/form-data" method="post"><input name="file" type="file"><input type="submit" value="上傳要識別的圖片"></form></body> """ return HTMLResponse(content=content) if __name__ == '__main__': uvicorn.run(app, host="127.0.0.1", port=8000) class NumpyEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, (np.int_, np.intc, np.intp, np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64)): return int(obj) elif isinstance(obj, (np.float_, np.float16, np.float32,np.float64)): return float(obj) elif isinstance(obj, (np.ndarray,)): return obj.tolist() return json.JSONEncoder.default(self, obj)9.4、PaddleOCR調用代碼"""Created on Sat Sep 18 10:56:10 2021
@author: 以數據之名@class:paddleocr_test"""
from paddleocr import PaddleOCR, draw_ocr
def ocr_interface(img_path,language): "列印任何傳入的字符串" print(img_path,language) ocr = PaddleOCR(use_angle_cls=True, use_gpu=False, lang=language) result = ocr.ocr(img_path, cls=True) save_result_img(img_path,result) return result
ocr = PaddleOCR(use_angle_cls=True, use_gpu=False, lang="ch") img_path = './imgs/00056221.jpg'result = ocr.ocr(img_path, cls=True)for line in result: print(line)
def save_result_img(img_path,result): image = Image.open(img_path).convert('RGB') boxes = [line[0] for line in result] txts = [line[1][0] for line in result] scores = [line[1][1] for line in result] im_show = draw_ocr(image, boxes, txts, scores, font_path='./fonts/simfang.ttf') im_show = Image.fromarray(im_show) print(os.path.split(img_path)) im_show.save('./ocr_result/result-'+os.path.split(img_path)[1]) save_result_img(img_path,result)
10.1、web服務
http://127.0.0.1:8000/,web上傳文件,測試OCR識別接口。
10.2、Postman測試
Postman測試基本三要素:
10.3、代碼測試
這裡以python語言,作為示例接口請求代碼。
import requestsurl = "http://127.0.0.1:8000/paddleocr/"path = "d:/00056221.jpg"files = {'file': open(path, 'rb')}r = requests.post(url, files=files)print(r.text)
09|Python專題
愛樂之程系列之愛情樹
愛樂之程系列之5201314
愛樂之程系列之愛要說出來
雖小編一己之力微弱,但讀者眾星之光璀璨。小編敞開心扉之門,還望傾囊賜教原創之文,期待之心滿於胸懷,感激之情溢於言表。一句話,歡迎聯繫小編投稿您的原創文章!