領域(輪郭)の属性情報

ここでは物体の特徴を表す時によく使われる輪郭の属性情報(ソリディティ, 等価直径, マスク画像,平均値など)について学びます. より詳細な情報については Matlab regionprops documentation を参照してください.

(NB : 重心,面積,周囲長なども輪郭の属性情報ですが,前のチュートリアルで既に扱いました)

1. アスペクト比

アスペクト比(Aspect Ratio)は物体を囲む外接長方形の縦幅(height)に対する横幅(width)の比です.

Aspect \; Ratio = \frac{Width}{Height}

x,y,w,h = cv2.boundingRect(cnt)
aspect_ratio = float(w)/h

2. Extent

Extentは外接矩形の面積に対する輪郭が占める面積の比です.

Extent = \frac{Object \; Area}{Bounding \; Rectangle \; Area}

area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
rect_area = w*h
extent = float(area)/rect_area

3. Solidity

Solidityは凸包(領域を囲む最小の外接多角形)の面積に対する輪郭の面積の比です.

Solidity = \frac{Contour \; Area}{Convex \; Hull \; Area}

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area

4. 等価直径

等価直径(Equivalent Diameter)は輪郭の面積と同じ面積を持つ円の直径です.

Equivalent \; Diameter = \sqrt{\frac{4 \times Contour \; Area}{\pi}}

area = cv2.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi)

5. 傾き

傾き(Orientation)は物体が向いている方向を意味します.以下の計算方法で長径(MA: Major Axis)と短径(ma: Minor Axis)も同時に計算できます.

(x,y),(MA,ma),angle = cv2.fitEllipse(cnt)

6. マスクと画素点

マスク(Mask)とは物体が占める領域とそれ以外の領域を区別するためのもので,画素点(Pixel Point)とはマスクを構成する全ての点を指します.物体を構成する全ての点の情報が必要になる時は,以下のようにします:

mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[cnt],0,255,-1)
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv2.findNonZero(mask)

3行目と4行目はそれぞれNumpyの関数とOpenCVの関数を使っていますが,全く同じ処理です.結果も同じ結果が得られますが,若干の違いがあります.Numpyは座標を (row, column) の形式で出力するのに対して,OpenCVは (x,y) の形式で出力します.そのため,それぞれの結果は置き換えられます.ここで row = xcolumn = y という関係になります.

7. 最大値,最小値とその位置

画像中(対象領域中)の画素値の最大値,最小値及び対応する画素の位置を調べるには以下のようにします.

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(imgray,mask = mask)

8. 平均色と平均値

物体の平均色の計算もできます.グレースケール画像であれば平均値になります.マスクを指定すると,注目領域を対象とした計算をします.

mean_val = cv2.mean(im,mask = mask)

9. 端点

端点(Extreme Points)は物体の上橋(topmost),下端(bottommost),右端(rightmost),左端(leftmost)の点を意味します.

leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

例えばインドの地図に対して端点を求めると,以下のようになります :

Extreme Points

補足資料

課題

  1. このチュートリアルで紹介した以外にも,MatLabの領域に関する属性情報はまだまだあるので,自分で実装してみてください.