私はPythonとOpenCVを使ってスクリプトを開発し、スキャンされた計装図上のハイライトされた領域を検出し、TesseractのOCR関数を使ってテキストを出力しようとしています。私のワークフローではまず関心領域の一般的な周辺を検出し、処理ブロックを適用してテキストのブロック(線、枠線、ノイズ)以外のすべてを削除します。処理された画像は、TesseractのOCRエンジンに送られます。円の枠の内側からテキストを抽出する
このワークフローはイメージの約半分で動作しますが、残りのテキストは境界線に触れるために残ります。
ステップ1:InRangeを使用してハイライトの色範囲でマスクを作成し、関心領域を見つけます。
手順2:関心のある輪郭を描き、切り抜き、ファイルに保存します。
---参考コードは---ここで始まる
ステップ3:閾値画像とキャニーエッジ検出を適用
ステップ4:エッジを輪郭と、cv2.approxPolyDPを使用して見て円形の形状にそれらをフィルタリングします頂点が8より大きい頂点で実行されます。第1または第2の最大の輪郭を取ることは、通常、内側のエッジに対応します。
ステップ5:マスクとビット単位の操作を使用して、輪郭内のすべてが白い背景イメージに転送されます。画像をノイズ除去し、OCRエンジンに供給される最終的な画像を作成するために、膨張および侵食が適用される。
import cv2
import numpy as np
import pytesseract
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract'
d_path = "Test images\\"
img_name = "cropped_12.jpg"
img = cv2.imread(d_path + img_name) # Reads the image
## Resize image before calculating contour
height, width = img.shape[:2]
img = cv2.resize(img,(2*width,2*height),interpolation = cv2.INTER_CUBIC)
img_orig = img.copy() # Makes copy of original image
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # Convert to grayscale
# Apply threshold to get binary image and write to file
_, img = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Edge detection
edges = cv2.Canny(img,100,200)
# Find contours of mask threshold
_, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Find contours associated w/ polygons with 8 sides or more
cnt_list = []
area_list = [cv2.contourArea(c) for c in contours]
for j in contours:
poly_pts = cv2.approxPolyDP(j,0.01*cv2.arcLength(j,True),True)
area = cv2.contourArea(j)
if (len(poly_pts) > 8) & (area == max(area_list)):
cnt_list.append(j)
cv2.drawContours(img_orig, cnt_list, -1, (255,0,0), 2)
# Show contours
cv2.namedWindow('Show',cv2.WINDOW_NORMAL)
cv2.imshow("Show",img_orig)
cv2.waitKey()
cv2.destroyAllWindows()
# Zero pixels outside circle
mask = np.zeros(img.shape).astype(img.dtype)
cv2.fillPoly(mask, cnt_list, (255,255,255))
mask_inv = cv2.bitwise_not(mask)
a = cv2.bitwise_and(img,img,mask = mask)
wh_back = np.ones(img.shape).astype(img.dtype)*255
b = cv2.bitwise_and(wh_back,wh_back,mask = mask_inv)
res = cv2.add(a,b)
# Get rid of noise
kernel = np.ones((2, 2), np.uint8)
res = cv2.dilate(res, kernel, iterations=1)
res = cv2.erode(res, kernel, iterations=1)
# Show final image
cv2.namedWindow('result',cv2.WINDOW_NORMAL)
cv2.imshow("result",res)
cv2.waitKey()
cv2.destroyAllWindows()
コードが動作する場合、これらは、出力取得画像である: Working
しかし、テキストは円形の境界に触れる場合において、テキストのコード前提部分が大きいの一部であります最後の文字は無視されます。例: Not working
この問題を回避するための処理手順はありますか?それとも別のアプローチですか?私は境界線を検出しようとするためにハフ・サークル・トランスフォームを使用しようとしましたが、かなり複雑で、輪郭線として機能しません。
私はOpenCVとPythonにはかなり新しいので、どんな助けにも感謝します。
Douglas-Peuckerアルゴリズムのパラメータで再生すると、元の結果が出力されるか、結果が出力されません。しかし、境界線の形状を近似する最も簡単な方法は、輪郭にcv2.minEnclosingCircle()関数を使用することでした。 –
ダグラス・ピーッカーがこのユースケースに限定されている理由を知りましたか? – hackela