らせん状のノートに書かれたテキストの画像があります。紙に横線があります。画像から横線を取り除きたいのですが。
グーグルしながら、私はうまくいくと思う解決策を見つけました: 形態学的操作を使用して水平線と垂直線を抽出する 解決策はC++であったため、Pythonに変換しました。そのソリューションで提供されるサンプル画像ではうまく機能しますが、私の画像では機能しないようです。
私のイメージでそれを実行している間、私はこれらの結果を得ます:
以下は、C++から翻訳したPythonコードです。
#cpp code converted from http://docs.opencv.org/3.2.0/d1/dee/tutorial_moprh_lines_detection.html
import cv2
import numpy as np
img = cv2.imread("original.jpg")
img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img = cv2.bitwise_not(img)
th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2)
cv2.imshow("th2", th2)
cv2.imwrite("th2.jpg", th2)
cv2.waitKey(0)
cv2.destroyAllWindows()
horizontal = th2
vertical = th2
rows,cols = horizontal.shape
horizontalsize = cols / 30
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize,1))
horizontal = cv2.erode(horizontal, horizontalStructure, (-1, -1))
horizontal = cv2.dilate(horizontal, horizontalStructure, (-1, -1))
cv2.imshow("horizontal", horizontal)
cv2.imwrite("horizontal.jpg", horizontal)
cv2.waitKey(0)
cv2.destroyAllWindows()
verticalsize = rows / 30
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))
vertical = cv2.erode(vertical, verticalStructure, (-1, -1))
vertical = cv2.dilate(vertical, verticalStructure, (-1, -1))
cv2.imshow("vertical", vertical)
cv2.imwrite("vertical.jpg", vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()
vertical = cv2.bitwise_not(vertical)
cv2.imshow("vertical_bitwise_not", vertical)
cv2.imwrite("vertical_bitwise_not.jpg", vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()
#step1
edges = cv2.adaptiveThreshold(vertical,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,-2)
cv2.imshow("edges", edges)
cv2.imwrite("edges.jpg", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
#step2
kernel = np.ones((2, 2), dtype = "uint8")
dilated = cv2.dilate(edges, kernel)
cv2.imshow("dilated", dilated)
cv2.imwrite("dilated.jpg", dilated)
cv2.waitKey(0)
cv2.destroyAllWindows()
# step3
smooth = vertical.copy()
#step 4
smooth = cv2.blur(smooth, (4,4))
cv2.imshow("smooth", smooth)
cv2.imwrite("smooth.jpg", smooth)
cv2.waitKey(0)
cv2.destroyAllWindows()
#step 5
(rows, cols) = np.where(img == 0)
vertical[rows, cols] = smooth[rows, cols]
cv2.imshow("vertical_final", vertical)
cv2.imwrite("vertical_final.jpg", vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()
線を削除するために、元の画像でもImageMagikを試しました。
ImageMagikを使用するとより良い結果が得られますが、それでも完全に正確ではありません。
convert original -morphology close:3 "1x5: 0,1,1,1,0" original_im.jpg
あなたのケースは、あなたがあなたのソリューションに基づいているチュートリアルで提供されたものより簡単ではありません。この方法では、文字の水平部分が線として扱われることがあるので、線を100%でフィルタリングすることはできません。
期待値(実際には指定していません)、特に期待する精度によっては、行を見つけるのではなく、文字を見つけようとする場合があります。これにより、より堅牢になります。
コードについては、画像上の水平線を見つけた直後(コードの_verticalsize = rows / 30
_行の前)に数行のコードを追加することで、いくつかの結果を得ることができます。ハーフサイズの画像を作成しました。
horizontalsize = int(cols/30) の結果
horizontalsize = int(cols/15) の結果
繰り返しますが、私はあなたの場合、それらのアプローチでは正確ではないことを強調します。これがスニペットです:
_#inverse the image, so that lines are black for masking
horizontal_inv = cv2.bitwise_not(horizontal)
#perform bitwise_and to mask the lines with provided mask
masked_img = cv2.bitwise_and(img, img, mask=horizontal_inv)
#reverse the image back to normal
masked_img_inv = cv2.bitwise_not(masked_img)
cv2.imshow("masked img", masked_img_inv)
cv2.imwrite("result2.jpg", masked_img_inv)
cv2.waitKey(0)
cv2.destroyAllWindows()
_
私が提供した画像がある程度満足できる場合は、horizontalsize
で遊んでみてください。 getStructuringElement
関数が期待するのはhorizontalsize = int(cols / 30)
なので、私はint変換も使用しました。
結果に対して平滑化と形態を試すこともできます。これにより、文字が少し読みやすくなります。