end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

opencv.findContours() による 画像の境界(輪郭)探索

以下、記載の通り。

外壁面のみ、描画したかったのですが、それは今後

#!/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

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 )
    i  = 0
    for contour in contours:
          #  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,
                         contours,
                         i,    # 表示する輪郭. 全表示は-1
                         color,
                         2)    # 等高線の太さ
        print i
        i += 1
        if i > 3:
            break
    new_file = 'new_' + time_str + '.png'
    cv2.imwrite(new_file, img_org)


if __name__ == '__main__':
    main()

↑こう書くと↓こう変換されます。途中の2値化画像もあります

f:id:end0tknr:20120723195236j:plain:w350

f:id:end0tknr:20171104153458p:plain:w270 f:id:end0tknr:20171104153504p:plain:w270