opencv.findContours() による 画像の境界(輪郭)探索 - end0tknr's kipple - 新web写経開発
先日のエントリの続き。詳細は、以下参照。
#!/usr/local/bin/python # -*- coding: utf-8 -*- from PIL import Image import cv2 from datetime import datetime import matplotlib matplotlib.use('Agg') import matplotlib.pylab as plb import numpy as np import sys # http://lang.sist.chukyo-u.ac.jp/classes/OpenCV/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html def main(): org_file = sys.argv[1] img_org = cv2.imread(org_file) # グレースケール化 img_tmp = cv2.cvtColor(img_org, cv2.COLOR_BGR2GRAY) # 2値化 # - cv2.findContours()は、黒と背景、白を物体として判定する為 # cv2.THRESH_BINARY_INV で 2値化し、ネガポジ反転 # - cv2.THRESH_BINARY は単なる2値化 ret, img_tmp = cv2.threshold(img_tmp, 250, # 閾値 256, # 画素値の最大値 cv2.THRESH_BINARY_INV) # 2値化type time_str = datetime.now().strftime("%Y%m%d_%H%M%S") tmp_file = 'tmp_' + time_str + '.png' cv2.imwrite(tmp_file, img_tmp) # 境界線探索 # - 第2引数: # - cv2.RETR_EXTERNAL は最外周のみ探索 # - cv2.RETR_TREE は全境界(輪郭? 等高線?)を探索 # - 返り値: # - contours : 探索された境界 # - hierarchy: 境界が複数ある場合の階層 ret, contours, hierarchy = cv2.findContours(img_tmp, cv2.RETR_EXTERNAL, # cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE ) # cv2.CHAIN_APPROX_NONE ) contours.sort(key=cv2.contourArea, reverse=True) i = 0 for contour in contours: arclen = cv2.arcLength(contour, True) # 対象領域が閉曲線の場合、True approx = cv2.approxPolyDP(contour, 0.005*arclen, # 近似の具合? True) print approx # B G R color = \ ( 0, 0,255) if i % 6 == 0 else \ ( 0,255, 0) if i % 6 == 1 else \ (255, 0, 0) if i % 6 == 2 else \ ( 0,255,255) if i % 6 == 3 else \ (255,255, 0) if i % 6 == 4 else (255, 0,255) # 境界の描画 ( img_org データに contours データをマージ ) cv2.drawContours(img_org, [approx], -1, # 表示する輪郭. 全表示は-1 color, 2) # 等高線の太さ i += 1 if i > 3: break new_file = 'new_' + time_str + '.png' cv2.imwrite(new_file, img_org) if __name__ == '__main__': main()
↑こう書くと↓こう変換されます。
以前の単純な境界抽出と比較すると、窓の部分が、直線になっていることが分かります。