Python : 最小外接円 Opencv

Opencvを使った最小外接円についてです。

円の検出というとハフさん?が作ったと思われるHoughもありますが、

ハフ関数は円のサイズや投票数があるので、結構うまく使うのが難しいな~と

感じているのですが、最小外接円のほうはパラメータみたいなものがないので、

使い勝手が良いと思っているのと、

最小外接円を使ったほうが、再現性が良いと思っています。

 

まずはモジュールのインポート

import cv2

今回使う画像はこれ(ペイントで適当に作りました)

f:id:Kangkang1981:20200328224924j:plain

 

画像を読み取って、グレイ→二極化までします。

#gray画像を作成
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#二極化
ret2,th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

#あとで変えやすいように、いつも変数を作っています。

cimg = th

 

前の記事でも書きましたが、contourでの輪郭抽出

※詳細はこちらをご参照ください。

contours, hierarchy = cv2.findContours(cimg,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))

 

この後に使うのは下記の関数です。

このminEnclosingCircle()を入れるだけで、この検出した領域の

座標(x,y)と半径(radius)が検出されます。

(x,y),radius = cv2.minEnclosingCircle(cnt)

後は、円を書くだけです。
cv2.circle(frame,(int(x),int(y)),int(radius),(0,0,255),3)

f:id:Kangkang1981:20200328225545j:plain

 

プログラムの詳細は下記です。

import cv2

frame=cv2.imread('form2.jpg')

#gray画像を作成
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#二極化
ret2,th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

cimg = th

contours, hierarchy = cv2.findContours(cimg,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))

for i, cnt in enumerate(contours):
        # 輪郭の面積を計算する。
        area = cv2.contourArea(cnt)
        # 抽出する範囲を指定
        if area > 100 and area < 10000:
            #最小外接円を計算する
            (x,y),radius = cv2.minEnclosingCircle(cnt)
            cv2.circle(frame,(int(x),int(y)),int(radius),(0,0,255),3)

cv2.imshow('frame',frame)
cv2.imwrite('min_contour.jpg',frame)
            
#キー入力を待つ
cv2.waitKey(0)
#全ての開いたウインドウ閉じる
cv2.destroyAllWindows()

今までにpythonについて書いた記事はここにリンクを貼ってあります。

興味があればぜひご覧ください。