web-dev-qa-db-ja.com

OpenCVで画像から空白を削除する方法は?

次の画像には、テキストとテキストの下に空白がたくさんあります。 2つ目の画像のように余白をトリミングします。

enter image description here

トリミングされた画像

enter image description here

これが私がやったことです

>>> img = cv2.imread("pg13_gau.jpg.png")
>>> gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
>>> edged = cv2.Canny(gray, 30,300)
>>> (img,cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
>>> cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:10]
14
Anthony

多くのコメントで言及されているように、最善の方法は、画像を反転して黒いテキストを白くし、画像内のゼロ以外のすべての点を見つけて、最小の境界ボックスを決定することです。この境界ボックスを使用して、最終的に画像をトリミングできます。輪郭の検索は非常に負荷が高く、特にテキストが軸に揃えられているため、ここでは必要ありません。 cv2.findNonZerocv2.boundingRect の組み合わせを使用して、必要なことを行うことができます。

したがって、次のようなものが機能します。

import numpy as np
import cv2

img = cv2.imread('ws.png') # Read in the image and convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = 255*(gray < 128).astype(np.uint8) # To invert the text to white
coords = cv2.findNonZero(gray) # Find all non-zero points (text)
x, y, w, h = cv2.boundingRect(coords) # Find minimum spanning bounding box
rect = img[y:y+h, x:x+w] # Crop the image - note we do this on the original image
cv2.imshow("Cropped", rect) # Show it
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("rect.png", rect) # Save the image

上記のコードは、冒頭で話したことを正確に示しています。画像を読み込みましたが、何らかの理由で画像がカラーになっているため、グレースケールに変換します。トリッキーな部分はコードの3行目で、128の強度を下回ってしきい値を設定しているため、暗いテキストが白くなります。ただし、これはバイナリイメージを生成するので、uint8に変換し、255でスケーリングします。これにより、テキストが本質的に反転します。

次に、この画像を指定すると、cv2.findNonZeroを使用してゼロ以外のすべての座標が検出され、最後にこれをcv2.boundingRectに挿入して、左上隅およびwidthおよびheightの境界ボックス。最後にこれを使用して画像をトリミングできます。これは元の画像で行い、反転した画像では行わないことに注意してください。単純にNumPy配列のインデックスを使用してクロッピングを行います。

最後に、画像を表示して動作することを示し、ディスクに保存します。


私は今この画像を取得します:

enter image description here


2番目の画像の場合、右境界線と下境界線の一部を削除することをお勧めします。最初に画像を切り抜くことでそれを行うことができます。次に、この画像には非常に小さなノイズのあるピクセルが含まれています。非常に小さなカーネルを使用して形態学的オープニングを実行してから、上記で説明したロジックをやり直すことをお勧めします。

したがって:

import numpy as np
import cv2

img = cv2.imread('pg13_gau_preview.png') # Read in the image and convert to grayscale
img = img[:-20,:-20] # Perform pre-cropping
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = 255*(gray < 128).astype(np.uint8) # To invert the text to white
gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, np.ones((2, 2), dtype=np.uint8)) # Perform noise filtering
coords = cv2.findNonZero(gray) # Find all non-zero points (text)
x, y, w, h = cv2.boundingRect(coords) # Find minimum spanning bounding box
rect = img[y:y+h, x:x+w] # Crop the image - note we do this on the original image
cv2.imshow("Cropped", rect) # Show it
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("rect.png", rect) # Save the image

注:プライバシー保護のため、出力画像は削除されました