つれづれなる備忘録

日々の発見をあるがままに綴る

OpenCVの使い方27 ~ 輪郭抽出4

今回は前回のOpenCVを用いた輪郭近似の続きについて紹介したい。

atatat.hatenablog.com

1. 円・楕円近似

 円:最小外接円で近似する場合は、cv2.minEnclosingCircleにより中心座標と半径を求める。描画は円を描画するcv2.circleを用いる。

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.circle(cnt_img,center,radius,255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

C字が丸いので、円に対してかなりフィッティングできていることがわかる。

外接円近似
外接円近似

正円ではなく楕円で近似する場合はcv2.fitEllipseを用いる。楕円中心、長軸・短軸長さ、回転角が出力されるが、cv2.ellipseで描画することができる。

ellipse = cv2.fitEllipse(cnt)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.ellipse(cnt_img,ellipse,255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

C字のくぼみの関係で若干横方向に長い楕円として近似される。

外接楕円近似
外接楕円近似

2. 三角形近似

 三角形で近似する場合は、cv2.minEnclosingTriangleを用いる。三角形の座標が出力されるので、cv2.polylinesで多角形を描画する。

retval, triangle = cv2.minEnclosingTriangle(cnt)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
tr = triangle.astype(np.int32).reshape((-1, 2))
cnt_img=cv2.polylines(cnt_img, [tr], True, 255, 2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

"三角形近似"
三角形近似

三角形の頂点が収まっていないので、三角形の座標値を調べてみる。

tr
>array([[ 90, 146],
       [285, 146],
       [181, -10]], dtype=int32)

3点目のy座標値が負になっていて、画像の範囲外に近似点があることをあらわしている。

3. 直線近似

最後に直線で近似する場合を紹介する。直線近似はデータ処理の直線近似を画像にあてはめたものでcv2.fitLineを用いることで、傾き(vy/vx)・直線が通過する点(x,y)を用いてcv2.lineで直線を描画する。

rows,cols = gray.shape[:2]
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.line(cnt_img,(cols-1,righty),(0,lefty),255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

直線近似
直線近似

3. まとめ

 今回は輪郭の近似としてとして円、楕円、三角形、直線について紹介した。