簡體   English   中英

Python + OpenCV:OCR 圖像分割

[英]Python + OpenCV: OCR Image Segmentation

我正在嘗試從這個收據的玩具示例中進行 OCR。 使用 Python 2.7 和 OpenCV 3.1。

在此處輸入圖片說明

灰度 + 模糊 + 外部邊緣檢測 + 收據中每個區域的分割(例如“類別”,稍后查看標記了哪個 - 在這種情況下是現金 -)。

當圖像“傾斜”以便能夠正確轉換然后“自動”分割收據的每個部分時,我覺得很復雜。

示例:

在此處輸入圖片說明

有什么建議嗎?

下面的代碼是一個例子,直到邊緣檢測,但是當收據像第一張圖像時。 我的問題不是圖像到文本。 是圖像的預處理。

任何幫助都非常感謝! :)

import os;
os.chdir() # Put your own directory

import cv2 
import numpy as np

image = cv2.imread("Rent-Receipt.jpg", cv2.IMREAD_GRAYSCALE)

blurred = cv2.GaussianBlur(image, (5, 5), 0)

#blurred  = cv2.bilateralFilter(gray,9,75,75)

# apply Canny Edge Detection
edged = cv2.Canny(blurred, 0, 20)

#Find external contour

(_,contours, _) = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

pyimagesearch上提供了有關您所描述的第一步的精彩教程(他們通常有很棒的教程)

簡而言之,如 Ella 所述,您必須使用cv2.CHAIN_APPROX_SIMPLE 稍微更健壯的方法是使用cv2.RETR_LIST而不是cv2.RETR_EXTERNAL然后對區域進行排序,因為即使在白色背景下它也應該可以正常工作/如果頁面在背景中刻有更大的形狀等。

來到問題的第二部分,分割字符的一個好方法是使用 OpenCV 中可用的最大穩定極值區域提取器 在我最近參與的一個項目中,可以在此處獲得 CPP 中的完整實現。 Python 實現將遵循(以下代碼適用於 OpenCV 3.0+。對於 OpenCV 2.x 語法,請在線檢查)

import cv2

img = cv2.imread('test.jpg')
mser = cv2.MSER_create()

#Resize the image so that MSER can work better
img = cv2.resize(img, (img.shape[1]*2, img.shape[0]*2))

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
vis = img.copy()

regions = mser.detectRegions(gray)
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions[0]]
cv2.polylines(vis, hulls, 1, (0,255,0)) 

cv2.namedWindow('img', 0)
cv2.imshow('img', vis)
while(cv2.waitKey()!=ord('q')):
    continue
cv2.destroyAllWindows()

這給出了輸出

在此處輸入圖片說明

現在,為了消除誤報,您可以簡單地循環遍歷 hulls 中的點,並計算周長(hulls[i] 中所有相鄰點之間的距離總和,其中 hulls[i] 是一個凸包中所有點的列表)。 如果周長太大,則將其歸類為非字符。

由於圖像的邊框為黑色,因此圖像上的診斷線即將出現。 可以通過在讀取圖像后立即添加以下行來簡單地刪除(第 7 行下方)

img = img[5:-5,5:-5,:]

這給出了輸出

在此處輸入圖片說明

我頭頂上的選項需要提取傾斜圖像的 4 個角。 這是通過使用做cv2.CHAIN_APPROX_SIMPLE代替cv2.CHAIN_APPROX_NONE找到輪廓時。 之后,您可以使用cv2.approxPolyDP並希望保留收據的 4 個角(如果您的所有圖像都像這樣,那么沒有理由不工作)。

現在使用cv2.findHomographycv2.wardPerspective根據源點校正圖像,源點是從傾斜圖像中提取的 4 個點和應該形成矩形的目標點,例如完整的圖像尺寸。

在這里您可以找到代碼示例和更多信息: OpenCV-Geometric Transformations of Images

這個答案也可能有用 - SO - Detect and fix text skew

編輯:將第二個鏈大約更正為cv2.CHAIN_APPROX_NONE

通過將前景中所需的文本轉換為黑色同時將不需要的背景轉換為白色來預處理圖像有助於提高 OCR 的准確性。 此外,刪除水平和垂直線可以改善結果。 這是去除不需要的噪聲(例如水平/垂直線)后的預處理圖像。 注意刪除的邊框和表格線

在此處輸入圖片說明

import cv2

# Load in image, convert to grayscale, and threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find and remove horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (35,2))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (0,0,0), 3)

# Find and remove vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,35))
detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (0,0,0), 3)

# Mask out unwanted areas for result
result = cv2.bitwise_and(image,image,mask=thresh)
result[thresh==0] = (255,255,255)

cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.waitKey()

嘗試使用描邊寬度變換。 該算法的 Python 3 實現位於SWTloc

安裝庫

pip install swtloc

運行swttransform

from swtloc import SWTLocalizer
from swtloc.utils import imgshowN, imgshow

swtl = SWTLocalizer()
imgpath = ...
swtl.swttransform(imgpaths=imgpath, text_mode = 'lb_df', gs_blurr=False ,
                  minrsw = 3, maxrsw = 10, max_angledev = np.pi/3)
mgshowN([swtl.orig_img, swtl.swt_mat, swtl.swt_labelled3C],
        ['Original Image', 'Stroke Width Transform', 'Connected Components'])

在此處輸入圖片說明

運行文本分組

respacket = swtl.get_grouped(lookup_radii_multiplier=.8, sw_ratio=2,
                 cl_deviat=[13,13,13], ht_ratio=2, 
                 ar_ratio=4, ang_deviat=30)

grouped_labels = respacket[0]
grouped_bubblebbox = respacket[1]
grouped_annot_bubble = respacket[2]

imgshowN([swtl.orig_img, grouped_annot_bubble],
        ['Original', 'Grouped Bubble BBox Annotation'])

在此處輸入圖片說明

swttransform函數和get_grouped函數中有多個參數,您可以使用它們來獲得所需的結果。

完全披露:我是這個圖書館的作者

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM