概要
3D分野の研究では、生成したモデルの精度を評価するために、ターゲットオブジェクトとのIoUを測ることがあります。
今回はボクセル表現の3次元モデルにおけるIoUをPythonで実装しました。
IoUとは
IoUはIntersection over Unionの事で、「2つの物体の領域がどれだけ重なっているか」を評価する指標です。
2D画像では物体検出などに用いられます。
例えば、物体Aと物体BのIoUを測る際は以下のように求めることができます。
IoU(A, B) = \frac{A \;\cap \; B}{A \; \cup \; B}
したがって、物体のAND領域をOR領域で割ることで、どれだけ重なっているかを求めることができるのです。
では3DモデルにおけるIoUとは、どのように求めるのでしょうか?
最もシンプルな方法は、3Dモデルをボクセル表現に変換し、その重なりを調べる事です。
ボクセル表現とは、2D画像を構成するピクセルの3次元版にあたります。この表現を用いれば、単純なAND, OR領域の算出でIoU計算ができます。
Pythonでの実装
まずはボクセル表現の3Dモデルを用意します。
もし3Dモデルがボクセル表現以外(メッシュや点群)の場合、Pythonの3D操作などで用いられるライブラリを用いる方法があります。
例)
- Trimesh... https://github.com/mikedh/trimesh
- Open3D... https://github.com/isl-org/Open3D
もし上記のライブラリでボクセル表現を取得した場合は、そこからnumpy配列を取得しましょう。
…といいつつ、ここら辺のライブラリの仕様が理解しきれていないため、具体的な方法はわかっていません。おそらくライブラリ内のget系関数やプロパティを活用すれば取得できるはず。
以下は実装になります。
def calculate_volume_IoU(preds, gt, thresh=0.4):
"""3次元IoU評価指標
Args:
preds (np.array): 推論ボクセル
gt (np,array): GTボクセル
thresh (float, optional): ボクセルの閾値. Defaults to 0.4.
Returns:
float: IoU値
"""
# 推論numpy配列の値が0,1(True, False)でない場合の処理
preds_occupy = preds >= thresh
# ボリュームの積集合を計算
intersection = np.logical_and(preds_occupy, gt[0, :, :, :, 0])
# 2つのボリュームの和集合を計算
union = np.logical_or(preds_occupy, gt[0, :, :, :, 0])
# IoU計算
volume_IoU = np.sum(intersection) / np.sum(union)
return volume_IoU
まとめ
3D表現の変換まわりについて分かったことがあれば、別途まとめたいです。
参考サイト