[英]How to remove noise artifacts from an image for OCR with Python OpenCV?
我有包含數字的圖像子集。 Tesseract 為 OCR 讀取每個子集。 不幸的是,對於某些圖像,原始圖像的裁剪不是最佳的。
因此,圖像頂部和底部存在一些偽影/殘留物,並妨礙 Tesseract 識別圖像上的字符。 然后我想擺脫這些工件並得到類似的結果:
首先,我考慮了一種簡單的方法:我將第一行像素設置為參考:如果沿 x 軸發現偽影(即,如果圖像被二值化,則為白色像素),我沿 y 軸將其移除,直到下一個黑色像素。 這種方法的代碼如下:
import cv2
inp = cv2.imread("testing_file.tif")
inp = cv2.cvtColor(inp, cv2.COLOR_BGR2GRAY)
_,inp = cv2.threshold(inp, 150, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
ax = inp.shape[1]
ay = inp.shape[0]
out = inp.copy()
for i in range(ax):
j = 0
while j in range(ay):
if out[j,i] == 255:
out[j,i] = 0
else:
break
j+=1
out = cv2.bitwise_not(out)
cv2.imwrite('output.png',out)
但結果一點都不好:
然后我偶然發現了來自 scipy 的 flood_fill function ( 這里),但發現它太耗時而且效率不高。 一個類似的問題被問到了這里,但沒有太大幫助。 也許可以考慮k-最近鄰方法? 我還發現在某些條件下合並相鄰像素的方法稱為增長方法,其中單鏈接是最常見的( 此處)。
你會推薦什么來去除上下偽影?
這是一個簡單的方法:
轉換為灰度后,我們用Otsu的閾值得到二值圖像
# Read in image, convert to 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]
接下來我們創建一個長的水平 kernel 並擴張以將數字連接在一起
# Create special horizontal kernel and dilate
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (70,1))
dilate = cv2.dilate(thresh, horizontal_kernel, iterations=1)
從這里我們檢測水平線並排序最大的輪廓。 這個想法是最大的輪廓將是數字的中間部分,其中數字都是“完整的”。 任何較小的輪廓都將是部分或截斷的數字,因此我們在這里將它們過濾掉。 我們把這個最大的輪廓畫到一個面具上
# Detect horizontal lines, sort for largest contour, and draw on mask
mask = np.zeros(image.shape, dtype=np.uint8)
detected_lines = cv2.morphologyEx(dilate, cv2.MORPH_OPEN, horizontal_kernel, iterations=1)
cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
break
現在我們有了所需數字的輪廓,我們只需按位 - 並使用我們的原始圖像並將背景着色為白色以獲得我們的結果
# Bitwise-and to get result and color background white
mask = cv2.cvtColor(mask,cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(image,image,mask=mask)
result[mask==0] = (255,255,255)
完整的完整代碼
import cv2
import numpy as np
# Read in image, convert to 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]
# Create special horizontal kernel and dilate
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (70,1))
dilate = cv2.dilate(thresh, horizontal_kernel, iterations=1)
# Detect horizontal lines, sort for largest contour, and draw on mask
mask = np.zeros(image.shape, dtype=np.uint8)
detected_lines = cv2.morphologyEx(dilate, cv2.MORPH_OPEN, horizontal_kernel, iterations=1)
cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
break
# Bitwise-and to get result and color background white
mask = cv2.cvtColor(mask,cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(image,image,mask=mask)
result[mask==0] = (255,255,255)
cv2.imshow('thresh', thresh)
cv2.imshow('dilate', dilate)
cv2.imshow('result', result)
cv2.waitKey()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.