簡體   English   中英

用於 OCR 的清潔圖像

[英]Cleaning image for OCR

我一直在嘗試清除 OCR 圖像:(線條)

在此處輸入圖片說明

我需要刪除這些行以有時進一步處理圖像並且我已經非常接近但很多時間閾值從文本中帶走了太多:

    copy = img.copy()
    blur = cv2.GaussianBlur(copy, (9,9), 0)
    thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,30)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
    dilate = cv2.dilate(thresh, kernel, iterations=2)

    cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    for c in cnts:
        area = cv2.contourArea(c)
        if area > 300:
            x,y,w,h = cv2.boundingRect(c)
            cv2.rectangle(copy, (x, y), (x + w, y + h), (36,255,12), 3)

編輯:此外,如果字體發生變化,使用常量數字將不起作用。 有沒有通用的方法來做到這一點?

這是一個想法。 我們將這個問題分解為幾個步驟:

  1. 確定平均矩形輪廓面積。 然后我們閾值查找輪廓並使用輪廓的邊界矩形區域進行過濾。 我們這樣做的原因是因為觀察到任何典型的字符都只會如此之大,而大噪聲將跨越更大的矩形區域。 然后我們確定平均面積。

  2. 刪除大的離群值輪廓。 我們再次遍歷輪廓,如果大輪廓比平均輪廓區域大5x ,則通過填充輪廓來刪除它們。 我們沒有使用固定的閾值區域,而是使用這個動態閾值來提高魯棒性。

  3. 用垂直內核擴張以連接字符 這個想法是利用字符在列中對齊的觀察結果。 通過使用垂直內核進行擴張,我們將文本連接在一起,因此該組合輪廓中不會包含噪聲。

  4. 去除小噪音 現在要保留的文本已連接,我們找到輪廓並刪除任何小於平均輪廓面積4x的輪廓。

  5. 按位與重建圖像 由於我們只有想要的輪廓來保留在我們的掩碼上,我們按位保留文本並得到我們的結果。


這是該過程的可視化:

我們用大津的閾值來獲得二值圖像,然后找到輪廓來確定平均矩形輪廓區域。 從這里我們通過填充輪廓去除以綠色突出顯示的大的離群值輪廓

在此處輸入圖片說明 在此處輸入圖片說明

接下來我們構建一個垂直內核膨脹以連接字符。 此步驟連接所有所需的文本以保留並將噪聲隔離為單個 blob。

在此處輸入圖片說明

現在我們找到輪廓並使用輪廓區域過濾以去除小噪聲

在此處輸入圖片說明

以下是以綠色突出顯示的所有移除的噪聲粒子

在此處輸入圖片說明

結果

在此處輸入圖片說明

代碼

import cv2

# Load image, grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Determine average contour area
average_area = [] 
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    average_area.append(area)

average = sum(average_area) / len(average_area)

# Remove large lines if contour area is 5x bigger then average contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    if area > average * 5:  
        cv2.drawContours(thresh, [c], -1, (0,0,0), -1)

# Dilate with vertical kernel to connect characters
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,5))
dilate = cv2.dilate(thresh, kernel, iterations=3)

# Remove small noise if contour area is smaller than 4x average
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < average * 4:
        cv2.drawContours(dilate, [c], -1, (0,0,0), -1)

# Bitwise mask with input image
result = cv2.bitwise_and(image, image, mask=dilate)
result[dilate==0] = (255,255,255)

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

注意:傳統的圖像處理僅限於閾值、形態學操作和輪廓過濾(輪廓近似、面積、縱橫比或斑點檢測)。 由於輸入圖像可能因字符文本大小而異,因此很難找到單一的解決方案。 您可能需要考慮使用機器/深度學習來訓練自己的分類器以獲得動態解決方案。

暫無
暫無

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

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