文章目錄
- 一、背景與環境搭建
- 二、文本檢測與識别
一、背景與環境搭建
OpenCV的文本識别流程:
- OpenCV EAST 文本檢測器執行文本檢測,
- 我們提取出每個文本 ROI 并将其輸入 Tesseract,進而建構完整的 OpenCV OCR 流程!
-
環境搭建
Tesseract (v4) 最新版本支援基于深度學習的 OCR,準确率顯著提高。底層的 OCR 引擎使用的是一種循環神經網絡(RNN)——LSTM 網絡。
pip install tesseract
pip install opencv-python
pip install pillow
pip install pytesseract
pip install imutils
安裝 tesseract-ocr 下載下傳位址:https://digi.bib.uni-mannheim.de/tesseract/
由于 tesseract-ocr安裝位址(如下左):
故添加環境變量(如上右):C:\Program Files (x86)\Tesseract-OCR
故需改 pytesseract.py :
tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract.exe'
- OpenCV OCR 文本識别流程圖
- 我們使用 OpenCV 的 EAST 文本檢測器來檢測圖像中的文本。
- EAST 文本檢測器将提供文本 ROI 的邊界框坐标。
- 我們将提取每個文本 ROI,将其輸入到 Tesseract v4 的 LSTM 深度學習文本識别算法。LSTM 的輸出将提供實際 OCR 結果。
- 我們将在輸出圖像上繪制 OpenCV OCR 結果。
整個過程中使用到的 Tesseract 指令必須在 pytesseract 庫下調用。在調用 tessarct 庫時,我們需要提供大量 flag。(tessarct --help)
最重要的三個 flag 是 -l、–oem 和 --ism。
$ tesseract --help-oem
OCR Engine modes:
0 Legacy engine only.
1 Neural nets LSTM engine only.
2 Legacy + LSTM engines.
3 Default, based on what is available.
-l flag 控制輸入文本的語言,本教程示例中使用的是 eng(英語),在這裡你可以看到 Tesseract 支援的所有語言:https://github.com/tesseract-ocr/tesseract/wiki/Data-Files。 –oem(OCR 引擎模式)控制 Tesseract 使用的算法類型。執行以下指令即可看到可用的 OCR 引擎模式:
–psm 控制 Tesseract 使用的自動頁面分割模式:
$ tesseract --help-psm
Page segmentation modes:
0 Orientation and script detection (OSD) only.
1 Automatic page segmentation with OSD.
2 Automatic page segmentation, but no OSD, or OCR.
3 Fully automatic page segmentation, but no OSD. (Default)
4 Assume a single column of text of variable sizes.
5 Assume a single uniform block of vertically aligned text.
6 Assume a single uniform block of text.
7 Treat the image as a single text line.
8 Treat the image as a single word.
9 Treat the image as a single word in a circle.
10 Treat the image as a single character.
11 Sparse text. Find as much text as possible in no particular order.
12 Sparse text with OSD.
13 Raw line. Treat the image as a single text line,
bypassing hacks that are Tesseract-specific.
對文本 ROI 執行 OCR,我發現模式 6 和 7 性能較好,但是如果你對大量文本執行 OCR,那麼你可以試試 3(預設模式)。
如果你得到的 OCR 結果不正确,那麼我強烈推薦調整 --psm,它可以對你的輸出 OCR 結果産生極大的影響。
$ tree --dirsfirst
.
項目包含一個目錄和兩個重要檔案:
- images/:該目錄包含六個含有場景文本的測試圖像。我們将使用這些圖像進行 OpenCV OCR 操作。
- frozen_east_text_detection.pb:EAST 文本檢測器。該 CNN 已經經過預訓練,可用于文本檢測。它是由 OpenCV 提供的,你也可以在「Downloads」部分下載下傳它。
- text_recognition.py:我們的 OCR 腳本。我們将逐行 review 該腳本。它使用 EAST 文本檢測器找到圖像中的文本區域,然後利用 Tesseract v4 執行文本識别。
-
EAST 文本檢測器生成兩個變量:
scores:文本區域的機率。
geometry:文本區域的邊界框位置。
關于腳本參數
-
我們的腳本需要兩個指令行參數:
–image:輸入圖像的路徑。
–east:預訓練 EAST 文本檢測器的路徑。
-
下列指令行參數是可選的:
–min-confidence:檢測到的文本區域的最小機率。
–width:圖像輸入 EAST 文本檢測器之前需要重新調整的寬度,我們的檢測器要求寬度是 32 的倍數。
–height:與寬度類似。檢測器要求調整後的高度是 32 的倍數。
–padding:添加到每個 ROI 邊框的(可選)填充數量。如果你發現 OCR 結果不正确,那麼你可以嘗試 0.05、0.10 等值。
二、文本檢測與識别
from imutils.object_detection import non_max_suppression
import numpy as np
import pytesseract
import argparse
import cv2
"""
EAST 文本檢測器生成兩個變量:
scores:文本區域的機率。
geometry:文本區域的邊界框位置。
"""
def decode_predictions(scores, geometry):
# grab the number of rows and columns from the scores volume, then
# initialize our set of bounding box rectangles and corresponding
# confidence scores
(numRows, numCols) = scores.shape[2:4]
rects = []
confidences = []
for y in range(0, numRows):
#提取分數(機率),然後是幾何資料,用于導出圍繞文本的潛在邊界框坐标
scoresData = scores[0, 0, y]
xData0 = geometry[0, 0, y]
xData1 = geometry[0, 1, y]
xData2 = geometry[0, 2, y]
xData3 = geometry[0, 3, y]
anglesData = geometry[0, 4, y]
for x in range(0, numCols): # 循環列數
if scoresData[x] < args["min_confidence"]: # 忽略低置信度
continue
# 計算偏移因子作為我們的結果特征
# maps will be 4x smaller than the input image
(offsetX, offsetY) = (x * 4.0, y * 4.0)
# 提取預測的旋轉角并計算
angle = anglesData[x]
cos = np.cos(angle)
sin = np.sin(angle)
# 使用幾何體來推導bounding box的寬度和高度
h = xData0[x] + xData2[x]
w = xData1[x] + xData3[x]
# 計算文本預測bounding box的起始和結束(x,y)坐标
endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
startX = int(endX - w)
startY = int(endY - h)
# 将 bounding box坐标和機率得分添加到各自的清單中
rects.append((startX, startY, endX, endY))
confidences.append(scoresData[x])
return (rects, confidences) #傳回bounding boxes的元組及其置信度
"""
構造參數分析器并解析參數
"""
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str,
help="path to input image")
ap.add_argument("-east", "--east", type=str,
help="path to input EAST text detector")
ap.add_argument("-c", "--min-confidence", type=float, default=0.5,
help="minimum probability required to inspect a region")
ap.add_argument("-w", "--width", type=int, default=320,
help="nearest multiple of 32 for resized width")
ap.add_argument("-e", "--height", type=int, default=320,
help="nearest multiple of 32 for resized height")
ap.add_argument("-p", "--padding", type=float, default=0.0,
help="amount of padding to add to each border of ROI")
args = vars(ap.parse_args())
"""
加載+預處理我們的圖像并初始化關鍵變量
"""
image = cv2.imread(args["image"])
orig = image.copy()
(origH, origW) = image.shape[:2]
# 設定新的寬度和高度,然後确定寬度和高度的變化比。
(newW, newH) = (args["width"], args["height"])
rW = origW / float(newW)
rH = origH / float(newH)
# 調整圖像大小并擷取新的圖像尺寸
image = cv2.resize(image, (newW, newH))
(H, W) = image.shape[:2]
"""
EAST文本檢測器:
EAST檢測器模型定義兩個輸出層名稱:
第一個是輸出機率,
第二個可以用來導出文本的邊框坐标
"""
layerNames = [
"feature_fusion/Conv_7/Sigmoid",
"feature_fusion/concat_3"]
# 加載預訓練的EAST文本檢測器
print("[INFO] loading EAST text detector...")
net = cv2.dnn.readNet(args["east"])
"""
至少 OpenCV 3.4.2 才能調用 cv2.dnn.readNet
見證【奇迹】的第一步:确定文本位置
從圖像中建構一個BLOB(團),然後執行模型的前向傳遞以獲得兩個輸出層集合。
"""
blob = cv2.dnn.blobFromImage(image, 1.0, (W, H),
(123.68, 116.78, 103.94), swapRB=True, crop=False)
net.setInput(blob)
(scores, geometry) = net.forward(layerNames)
# 解碼預測,然後應用非極大值抑制來抑制弱重疊的 bounding boxes(包圍盒)。
(rects, confidences) = decode_predictions(scores, geometry)
boxes = non_max_suppression(np.array(rects), probs=confidences)
'''
識别文本
周遊邊界框,并處理結果
'''
results = []
for (startX, startY, endX, endY) in boxes: # 周遊 bounding box
# 根據相應比例縮放 bounding box 坐标
startX = int(startX * rW)
startY = int(startY * rH)
endX = int(endX * rW)
endY = int(endY * rH)
# 填充邊界框:同時計算x和y方向的增量
dX = int((endX - startX) * args["padding"])
dY = int((endY - startY) * args["padding"])
# 将邊界分别填充到邊界框的每一側。
startX = max(0, startX - dX)
startY = max(0, startY - dY)
endX = min(origW, endX + (dX * 2))
endY = min(origH, endY + (dY * 2))
# 提取被填充的 ROI
roi = orig[startY:endY, startX:endX]
# 設定 Tesseract config 參數(英語、LSTM神經網絡和單行文本)。
config = ("-l eng --oem 1 --psm 7")
text = pytesseract.image_to_string(roi, config=config)
# 将邊界框坐标和OCR文本添加到結果清單中
results.append(((startX, startY, endX, endY), text))
"""
輸出結果:
"""
# 将結果框的坐标從上到下排序
results = sorted(results, key=lambda r:r[0][1])
for ((startX, startY, endX, endY), text) in results:
print("OCR TEXT")
print("========")
print("{}\n".format(text))
# 剝離非ASCII文本,利用OpenCV的圖像繪制文本,然後繪制文本和bounding box邊框
text = "".join([c if ord(c) < 128 else "" for c in text]).strip()
output = orig.copy()
cv2.rectangle(output, (startX, startY), (endX, endY),
(0, 0, 255), 2)
cv2.putText(output, text, (startX, startY - 20),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)
cv2.imshow("Text Detection", output)
cv2.waitKey(0)
cv2.destroyAllWindows()
.py --east frozen_east_text_detection.pb \
--image images/example_01.jpg
[INFO] loading EAST text detector...
OCR TEXT
========
關于代碼運作:
Anaconda | python3.6 | OpenCV_tf
我的OpenCV有關的庫全都安裝在
OpenCV_tf
環境中,故我需要在此環境運作代碼。
權重及完整代碼
該代碼運作可能會因為依賴而報錯,請安裝完整依賴