import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import cv2
from PIL import Image
from sympy import *
from sympy.abc import a,b,c
from sympy import var
from rdlib2 import *
処理対象画像例
平滑化
daruma='daruma.jpg'
img = getstandardShape(cv2.imread(daruma,cv2.IMREAD_GRAYSCALE), unitSize=UNIT, thres=0.25)
plt.imshow(img)
#輪郭線抽出
# 輪郭情報
_image, contours, _hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 輪郭線追跡
cnt00 = contours[np.argmax([len(c) for c in contours])] # 最も長い輪郭
canvas = np.zeros_like(img)
canvas = cv2.drawContours(canvas,[cnt00],-1,255,2) # 輪郭線の描画
plt.scatter([cnt00[-10][0][0]],[cnt00[-10][0][1]],color="red") # 輪郭点列の先頭位置
plt.imshow(canvas)
OpenCV の輪郭線データのデータ構造
print(cnt00[:3],cnt00[-3:],type(cnt00))
[[[193 65]] [[192 66]] [[191 66]]]
[[[196 65]] [[195 65]] [[194 65]]]
<class 'numpy.ndarray'>
- OpenCV の findContours関数で、RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE を指定した場合、最外殻輪郭を構成する点列の座標が左回りで並ぶ
- 1つの座標データは [[x座標, y座標]] というリスト。カッコが2重であることに注意
- 開始点と終了点は重複していない
- 8連結のチェインである
ヒゲの除去
上の例で用いた画像では発生しないが、対象図形に幅1の部分がある場合、輪郭チェインに同一の座標が重複して現れることになる。もし、輪郭チェイン内の座標に唯一性が要求される場合には、次のプログラムを通してヒゲ要素を取り除くとよい。
# 輪郭データからのひげ除去
def shaver(cnt): # 輪郭点列のうち、ヒゲ要素を取り除く
# まず輪郭列のスタート部分がヒゲ要素を取り除く
while True:
if len(cnt) > 2 and list(cnt[1][0])==list(cnt[-1][0]): # 最初の点がヒゲの先端
cnt = cnt[1:-1]
else:
break
# 途中のヒゲ要素を取り除く
while True:
l = len(cnt)
for i in range(1,len(cnt)-1):
if list(cnt[i-1][0]) == list(cnt[i+1][0]):
cnt = np.r_[cnt[:i],cnt[i+2:]]
if l == len(cnt):
break
return cnt