PythonとOpenCVを使って画像の輪郭(ふち)を抽出する方法

スポンサーリンク

今日は、画像から輪郭を検出する方法について学びます。輪郭は、オブジェクトの洗練された境界線として定義され、オブジェクトを検出するのに非常に役立ちます。

詳しくはこちらをご覧ください。Pythonでエッジを検出するには?

スポンサーリンク

Pythonによる輪郭検出

それでは早速、PythonのOpenCVライブラリを使って、画像の輪郭を検出する方法を紹介します。

1. モジュールのインポート

まず、OpenCV と matplotlib を含む、画像をスクリーンにプロットするために必要なモジュールをインポートします。

1
2
import cv2
import matplotlib.pyplot as plt

2. プログラムへのイメージのロード

次のステップでは、imread関数を使ってファイルディレクトリからプログラムに画像をロードし、その画像をRGBフォーマットに変換します。

ここでは、subplotという形式で画像をプロットします。そのためのコードを以下に示す。

1
2
3
4
5
6
7
8
9
loaded_img = cv2.imread("image.jpg")
loaded_img = cv2.cvtColor(loaded_img, cv2.COLOR_BGR2RGB)
 
plt.figure(figsize=(20,20))
 
plt.subplot(2,2,1)
plt.title("Original Image")
plt.imshow(loaded_img)
plt.axis("off")

3. 画像のグレースケールへの変換

輪郭の検出をより良くするために,関数 cvtColor を用いて画像をグレースケール画像に変換します.画像をグレースケールに変換した後、main plotの2番目のsubplotにプロットします。

1
2
3
4
5
gray_image = cv2.cvtColor(loaded_img, cv2.COLOR_RGB2GRAY)
plt.subplot(2,2,2)
plt.title("Grayscale Image")
plt.imshow(gray_image,cmap="gray")
plt.axis("off")

4. バイナリ画像の取得

画像から不要なものを取り除き、重要なものだけに焦点を当てることができるため、画像処理が非常に簡単になります。

そのためのコードを以下に示します。2値画像はメインプロットの3番目のスロットにプロットする予定です。

1
2
3
4
5
_, binary_img = cv2.threshold(gray_image, 225, 255, cv2.THRESH_BINARY_INV)
plt.subplot(2,2,3)
plt.title("Binary Image")
plt.imshow(binary_img,cmap="gray")
plt.axis("off")

5. 輪郭の検出

最後のステップは,openCV ライブラリの findContours メソッドを用いて輪郭を検出し,画像上にその輪郭を描画することです.

そして,すべての画像を subplot にプロットします.そのコードは以下のようになります.

1
2
3
4
5
6
contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
final_image = cv2.drawContours(loaded_img, contours, -1, (0, 255, 0), 2)
plt.subplot(2,2,4)
plt.title("Contours detected Image")
plt.imshow(final_image,cmap="gray")
plt.axis("off")

出力プロット

上記で説明した手順全体の最終的な出力は以下の通りです。結果は非常に正確であることがわかります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import cv2
import matplotlib.pyplot as plt
 
loaded_img = cv2.imread("image1.png")
loaded_img = cv2.cvtColor(loaded_img, cv2.COLOR_BGR2RGB)
 
plt.figure(figsize=(20,20))
 
plt.subplot(2,2,1)
plt.title("Original Image")
plt.imshow(loaded_img)
plt.axis("off")
 
gray_image = cv2.cvtColor(loaded_img, cv2.COLOR_RGB2GRAY)
plt.subplot(2,2,2)
plt.title("Grayscale Image")
plt.imshow(gray_image,cmap="gray")
plt.axis("off")
 
_, binary_img = cv2.threshold(gray_image, 225, 255, cv2.THRESH_BINARY_INV)
plt.subplot(2,2,3)
plt.title("Binary Image")
plt.imshow(binary_img,cmap="gray")
plt.axis("off")
 
contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
final_image = cv2.drawContours(loaded_img, contours, -1, (0, 255, 0), 2)
plt.subplot(2,2,4)
plt.title("Contours detected Image")
plt.imshow(final_image,cmap="gray")
plt.axis("off")
 
plt.savefig('Contour_Detection_output_2.png', dpi = 1000,bbox_inches = 'tight')
plt.tight_layout()
plt.show()

輪郭抽出のための最終コード

 Contour Detection Output 1 Detecting Contours
Contour Detection Output 1

同じコードを別の画像でも試してみました。その結果は以下の通りです。

Contour Detection Output 2 Detecting Contours
Contour Detection Output 2

まとめ

これで画像から物体を検出するのに一歩近づきましたね。今日はオブジェクトの適切な境界を検出することを学びました!

これからも学習を続けてください。ハッピーコーディング!

お読みいただきありがとうございました。

タイトルとURLをコピーしました