【Python・OpenCV】輪郭の面積を計算するには(cv2.contourArea)

※当サイトではアフィリエイト広告を利用しています

Python プログラミング 画像処理

【Python・OpenCV】輪郭の面積を計算するには(cv2.contourArea)

はじめに

cv2.findContours関数で検出した輪郭は様々な解析を行い、そのデータは様々なアプリケーションで活用されます。
輪郭のデータは物体認識、セグメンテーションやオブジェクト追跡などに利用されますが、面積計算はよく利用される解析方法の一つです。

本記事では輪郭の面積を計算するcv2.contourArea関数を解説します。この関数を使うことで、画像内の輪郭(物体)の面積を正確に計算することができます。

(広告) OpenCV関連書籍をAmazonで探す

cv2.contourArea関数

cv2.contourArea関数は、cv2.findContoures関数で検出した輪郭データから輪郭の面積を計算する関数です。

cv2.contourArea(contour[, oriented])

引数

名称説明
contour(必須)・面積を計算したい輪郭
numpy.ndarrayオブジェクトで表現され、形状は(N,1,2)または(N,2)です。Nは輪郭を構成する点の数です。
oriented(オプション)・領域の方向フラグ
True の場合、関数は輪郭の方向 (時計回りまたは反時計回り) に応じて符号付きの領域値を返します。戻り値の符号で輪郭の方向を判断できます。
False を指定すると、絶対値が返されす。
・bool型(デフォルト:False

戻り値

輪郭の面積(float型)が返されます。
単位は「平方ピクセル」(または「ピクセル²」)です。

使い方

以下にサンプルコードを示します。

import cv2

# 画像読み込み(グレースケール)
image = cv2.imread("image.png", cv2.IMREAD_GRAYSCALE)

# 二値化
_, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# 輪郭を検出
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 輪郭の面積を計算
for i, contour in enumerate(contours):
    area = cv2.contourArea(contour)
    print(f"輪郭のインデックス: {i}, 輪郭の面積: {area}平方ピクセル")

このコードでは、最初に入力画像をグレースケールに変換し、二値化を行います。その後、cv2.findContours関数で輪郭を検出します。
最後に、cv2.contourArea関数で、それらの各輪郭の面積を求め出力します。
1つ目の輪郭について、cv2.contourArea関数の戻り値の型を確認しています。

入力画像はcv2.fincContours関数の紹介記事で使用したものと同じ、下の画像を使用しました。
記事で解説した通り、cv2.fincContours関数により7個の輪郭が検出されます。

複数のオブジェクトが存在する階層構造

結果は次の通りです。
各輪郭のインデックス値と面積を書き出します。
各輪郭のインデックスの値は、下の画像の通りとなります。

輪郭のインデックス: 0, 輪郭の面積: 259077.0平方ピクセル
輪郭のインデックス: 1, 輪郭の面積: 142908.0平方ピクセル
輪郭のインデックス: 2, 輪郭の面積: 75615.0平方ピクセル
輪郭のインデックス: 3, 輪郭の面積: 19042.0平方ピクセル
輪郭のインデックス: 4, 輪郭の面積: 19180.0平方ピクセル
輪郭のインデックス: 5, 輪郭の面積: 28556.0平方ピクセル
輪郭のインデックス: 6, 輪郭の面積: 30014.0平方ピクセル
複数のオブジェクトが存在する階層構造,mode : cv2.RETR_TREE、method : cv2.CHAIN_APPROX_NONEの結果

応用

cv2.contourArea関数の出力は平方ピクセルですが、実世界の単位に変換する必要がある場合は、以下のようなアプローチを取ることができます。

  1. 既知のサイズの物体を参照として使用する。
  2. 画像の撮影条件(カメラの距離、レンズの焦点距離など)を利用する。
  3. 画像に含まれるスケールバーや既知のサイズの物体を利用する。

例えば、画像内の1センチメートルが10ピクセルに相当することが分かっている場合、以下のように変換できます

area_pixels = cv2.contourArea(contour)
area_cm2 = area_pixels / (10 * 10)  # 1cm = 10ピクセルなので、1cm² = 10² = 100ピクセル²
print(f"面積: {area_cm2} 平方センチメートル")

このように、適切な変換を行うことでcv2.contourArea関数の戻り値を、実世界の単位に変換することが可能です。
ただし、正確な変換には画像の撮影条件や縮尺に関する正確な情報が必要となります。

おわりに

cv2.contourArea関数は画像内の物体に関する重要な情報を抽出し、より高度な画像解析の手助けとなる重要な関数と言えます。
単純な面積計算だけの機能ですが、形状分析、物体の大きさの比較や物体の形状を表す特徴量の一つとしての面積の使用など様々な応用が可能です。

ご質問や取り上げて欲しい内容などがありましたら、コメントをお願いします。
最後までご覧いただきありがとうございました。

■(広告)OpenCVの参考書としてどうぞ!■

参考リンク

-Python, プログラミング, 画像処理
-