以前、輪郭の内側の面積と周囲長の関係から円形度なる値を求め、円らしき領域を抽出する方法を行いました。
【OpenCV-Python】円形度
円形度とは、図形の面積と周囲長の関係から、円らしさの値を求めます。 円形度の詳細は以下のページを参照ください。 OpenCV的には、図形の面積はcontourArea()関数で、周囲長はarcLength()関数で求める事ができるので、これ...
この考え方を応用して、今度は、矩形度(長方形らしさ)なる値を求めて、矩形らしき領域を抽出する方法を考えてみたいと思います。
矩形(長方形)は、名刺や本、コピー用紙のように、割と良く目にする図形なので、応用範囲は広いかと思います。ただし、今回紹介する方法は、四角形の被写体を斜めから撮影して、台形のようになってしまう画像には対応できません。
今回は、OpenCVを用いて、輪郭の内側の面積をcontourArea()関数で求め、輪郭を囲う最小の矩形領域の面積をminAreaRect()関数で求めて、この2つの面積の比で、矩形度なる値を求めます。
ただし、矩形度という言葉や計算方法が教科書的に存在するのかは不明です。(私が勝手に言ってます。)
この2つの面積が一致していれば完全に矩形(長方形)となります。
矩形度(小) | 矩形度(中) | 矩形度(大) |
サンプルプログラム
矩形度を求め、下図の中から矩形らしい部分を抽出するサンプルプログラムは以下の通りです。
(サンプルプログラム)
import cv2
import numpy as np
def rectangularity(contour):
'''
矩形度を求める
Parameters
----------
contour : ndarray
輪郭の(x,y)座標の配列
Returns
-------
矩形度
'''
# 面積
area = cv2.contourArea(contour)
# 傾いた外接する矩形領域
_, (width, height), _ = cv2.minAreaRect(contour)
# 矩形度を返す
return area / width / height
# 8ビット1チャンネルのグレースケールとして画像を読み込む
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)
# 白黒反転して二値化
ret, img = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY_INV)
# 一番外側の輪郭のみを取得
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE )
# 画像表示用に入力画像をカラーデータに変換する
img_disp = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# 全ての輪郭を描画
cv2.drawContours(img_disp, contours, -1, (0, 0, 255), 2)
# 輪郭の点の描画
for contour in contours:
# 傾いた外接する矩形領域の描画
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.intp(box)
cv2.drawContours(img_disp,[box],0,(0,255,255), 1)
# 矩形度の計算
val = rectangularity(contour)
# 輪郭の矩形領域
x,y,w,h = cv2.boundingRect(contour)
# 矩形度の描画
cv2.putText(img_disp, f"{val:.3f}", (x, y-10), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 1, cv2.LINE_AA)
# 円らしい領域(円形度が0.85以上)を囲う
if val > 0.85:
cv2.rectangle(img_disp,(x-10,y-10),(x+w+10,y+h+10),(255,0,0),2) # 少し外側を囲う
cv2.imshow("Image", img_disp)
# キー入力待ち(ここで画像が表示される)
cv2.waitKey()
実行結果
関連記事
【OpenCV-Python】findContoursによる輪郭検出
OpenCV(Python)で二値化された画像中の白の部分の外側の輪郭のデータを取得するにはfindContours()関数を用います。 黒の部分の輪郭は、白の部分の内側の輪郭という認識になります。 findContours()関数で取得で...
【OpenCV-Python】輪郭(contour)の面積(contourArea)
OpenCVで二値化された領域の輪郭座標は、findContours関数を使えば取得することができます。 このときの戻り値である輪郭情報(contours)をcontourArea関数へ渡し面積を求めます。 ただし、求まる面積は、あくまでも...
【OpenCV-Python】輪郭(contour)の矩形領域の取得
OpenCVのfindContours関数などで得られた点の座標から、点を囲う矩形領域(四角形の領域)を取得するにはboundingRect関数を用います。 さらに、傾きを考慮した矩形領域を取得するにはminAreaRect関数を用います。...
【OpenCV-Python】円形度
円形度とは、図形の面積と周囲長の関係から、円らしさの値を求めます。 円形度の詳細は以下のページを参照ください。 OpenCV的には、図形の面積はcontourArea()関数で、周囲長はarcLength()関数で求める事ができるので、これ...
コメント