今日は、画像から輪郭を検出する方法について学びます。輪郭は、オブジェクトの洗練された境界線として定義され、オブジェクトを検出するのに非常に役立ちます。
詳しくはこちらをご覧ください。Pythonでエッジを検出するには?
Pythonによる輪郭検出
それでは早速、PythonのOpenCVライブラリを使って、画像の輪郭を検出する方法を紹介します。
この記事もチェック: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" )
|
この記事もチェック:PythonとOpenCVを使って画像分割|二値化やグレースケールの変換等を解説
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() |
輪郭抽出のための最終コード
同じコードを別の画像でも試してみました。その結果は以下の通りです。
まとめ
これで画像から物体を検出するのに一歩近づきましたね。今日はオブジェクトの適切な境界を検出することを学びました!
これからも学習を続けてください。ハッピーコーディング!
お読みいただきありがとうございました。