Symfoware

Symfowareについての考察blog

OpenCV + Pythonで特定の図形を検出する1(図形の領域を矩形で取得)

手書きのこんな図形

868_01.png

これをサンプルとし、図形中に矢印や星印が写っているか判定できるか試してみます。
こちらを参考にさせていただきました。
AVFoundation+OpenCVで矩形検出(「名刺撮影用カメラ」みたいなやつ作ってみました)

OpenCV 3.4.1 + Python 3.6.5の環境で試しています。


グレースケール



参考サイトのとおり、図形の検出を容易にするためグレースケール化。


  1. import cv2 as cv
  2. def main():
  3.     # ファイルを読み込み
  4.     image_file = 'target.png'
  5.     src = cv.imread(image_file, cv.IMREAD_COLOR)
  6.     img_gray = cv.cvtColor(src, cv.COLOR_RGB2GRAY)
  7.     # 結果を保存
  8.     cv.imwrite('result.png', img_gray)
  9.     
  10. if __name__ == '__main__':
  11.     main()



この時点での出力

868_02.png


しきい値を設定し、白黒の明瞭な画像に変換します。
途中、デバッグ用の画像をダンプしながら実行してみます。


  1. import cv2 as cv
  2. def main():
  3.     # ファイルを読み込み
  4.     image_file = 'target.png'
  5.     src = cv.imread(image_file, cv.IMREAD_COLOR)
  6.     # グレースケール化
  7.     img_gray = cv.cvtColor(src, cv.COLOR_RGB2GRAY)
  8.     # しきい値指定によるフィルタリング
  9.     retval, dst = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO_INV )
  10.     cv.imwrite('debug_1.png', dst)
  11.     # 白黒の反転
  12.     dst = cv.bitwise_not(dst)
  13.     cv.imwrite('debug_2.png', dst)
  14.     # 再度フィルタリング
  15.     retval, dst = cv.threshold(dst, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
  16.     # 結果を保存
  17.     cv.imwrite('result.png', dst)
  18.     
  19. if __name__ == '__main__':
  20.     main()




・debug_1.png
868_03.png

・debug_2.png
868_04.png

・result.png
868_05.png

きれいに図形の部分だけ強調することができました。



輪郭検出



解析用の画像の下準備ができたので、図形領域の抽出を行います。
findContoursで輪郭を抽出します。
【OpenCV; Python】findcontours関数のまとめ

取得できた領域の中で、極端に大きい・小さいものは除外していきます。


  1. import cv2 as cv
  2. def main():
  3.     # ファイルを読み込み
  4.     image_file = 'target.png'
  5.     src = cv.imread(image_file, cv.IMREAD_COLOR)
  6.     # 画像の大きさ取得
  7.     height, width, channels = src.shape
  8.     image_size = height * width
  9.     # グレースケール化
  10.     img_gray = cv.cvtColor(src, cv.COLOR_RGB2GRAY)
  11.     # しきい値指定によるフィルタリング
  12.     retval, dst = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO_INV )
  13.     # 白黒の反転
  14.     dst = cv.bitwise_not(dst)
  15.     # 再度フィルタリング
  16.     retval, dst = cv.threshold(dst, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
  17.     # 輪郭を抽出
  18.     dst, contours, hierarchy = cv.findContours(dst, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
  19.     
  20.     # この時点での状態をデバッグ出力
  21.     dst = cv.imread(image_file, cv.IMREAD_COLOR)
  22.     dst = cv.drawContours(dst, contours, -1, (0, 0, 255, 255), 2, cv.LINE_AA)
  23.     cv.imwrite('debug_1.png', dst)
  24.     dst = cv.imread(image_file, cv.IMREAD_COLOR)
  25.     for i, contour in enumerate(contours):
  26.         # 小さな領域の場合は間引く
  27.         area = cv.contourArea(contour)
  28.         if area < 500:
  29.             continue
  30.         # 画像全体を占める領域は除外する
  31.         if image_size * 0.99 < area:
  32.             continue
  33.         
  34.         # 外接矩形を取得
  35.         x,y,w,h = cv.boundingRect(contour)
  36.         dst = cv.rectangle(dst,(x,y),(x+w,y+h),(0,255,0),2)
  37.     # 結果を保存
  38.     cv.imwrite('result.png', dst)
  39.     
  40. if __name__ == '__main__':
  41.     main()




・debug_1.png
868_06.png

・result.png
868_07.png


図形の部分だけ矩形で囲うことができました。
次は、「矢印」や「星」の判定方法について考えてみます。



【参考URL】

AVFoundation+OpenCVで矩形検出(「名刺撮影用カメラ」みたいなやつ作ってみました)
【OpenCV; Python】findcontours関数のまとめ
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/04/30(月) 18:33:52|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<OpenCV + Pythonで特定の図形を検出する2(特徴量検出による図形の判定) | ホーム | Ubuntu 18.06 ServerにOpenCV 3.4.1をインストール(install-opencv.sh)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
https://symfoware.blog.fc2.com/tb.php/2163-8fca73e8
この記事にトラックバックする(FC2ブログユーザー)