アプリとサービスのすすめ

アプリやIT系のサービスを中心に書いていきます。たまに副業やビジネス関係の情報なども気ままにつづります

物体検出(yolov7)のバウンディングボックスから奥行きの距離(depth)を計算してみた

Jetsonに2つのカメラをつけて、それぞれに物体検出のyolov7で推論をかける。そこで得たbboxの位置座標から視差(disparity)を求めて、奥行きの距離(depth)を求めてみた。

その過程と結果の備忘録


1. データセットの用意
2. disparityからdipthを求める手順
3. パラメーターとDipthの計算式
4. yolov7でbboxを推論
5. 結果:bboxと計測値からdisparityとdepthの関係図


1. データセットの用意

JetsonでCSIカメラのimx219を2台使って、右(right) と左(left) 用カメラとして使った。

実際の使用した場面の画像

使ったCSIカメラ


2. disparityからdipthを求める手順

下のサイトを参考にした。

webカメラ2台で距離測定その2

disparityの公式図

参考サイトによると、上のdisparityの公式を近似式で求めることができ、その結果disparityとdepthは反比例する関係になる。

・disparityが大きくなればdepthは小さくなる
・disparityが小さくなればdepthは大きくなる




参考サイトだとopencvで物体の重心からdepthを求めてだけど、今回は物体検出のbboxの位置座標からdisparityを求めた。

opencvを使ったdisparityからdipthの計算手順

1. カメラから画像を取得
2. 色抽出&二値化
3. 平滑化処理
4. 対象の重心位置の推定
5. 左右の画像から得られた対象の重心位置の差を求める
6. 重心位置の差から距離を求める


物体検出を使ったdisparityからdipthの計算手順

1. カメラから画像を取得
2. 物体検出で推論してbboxを取得
3. 左右のbboxのx座標の差の絶対値を求める
4. 3からdipth(距離)を求める




3. パラメーターとDipthの計算式

カメラとかの採寸やサイズは下の通り。

各変数の値を求めた結果、dipthの計算式は下のようになった。

パラメーター

画像サイズ:(Width, Height) = (1280, 960)

焦点距離:0.315 cm. ( f= 0.315

カメラ間の距離:2.6 cm. ( T= 2.6

画像素子:2.8μm = 0.00028 cm ( imgelement= 0.00028

Depth計算式

dipth(cm)= \dfrac {Tf} {imgelement \times disparity} = \dfrac {2925} {disparity}(cm)




4. yolov7でbboxを推論

下がyolov7で検出した画像。クラスが間違ってるのは後処理をすっ飛ばしてるからだけど、今は関係ないので割愛。


物体検出(yolov7)のバウンディングボックスから奥行きの距離(depth)を計算してみた

今回はbboxのrightとleftのx座標を引き算して、その絶対値を求めて、disparityを求める。


5. 結果:bboxと計測値からdisparityとdepthの関係図

下が大まかな計測値を表にしてグラフ化したもの。
disparityとdipthは計算式から求めた。


import pandas as pd

# 表の項目 :index, right_x, right_y, right_w, right_h, left_x. left_y, left_w, left_h, disparity
columns = ['idx', 'Lx', 'Ly', 'Lw', 'Lh', 'Rx', 'Ry', 'Rw', 'Rh']
# listed は計測値のlist
df = pd.DataFrame(listed, columns=columns)


# 計算式
def cm_disparity(x, y):
    disp = abs(x-y)
    return disp

def dist_formula(disparity):
    T = 2.6 # cm
    f = 0.315 # cm
    img_element = 0.0001*2.8 # cm
    K = int(T*f/img_element) # 2925
    dist = K/disparity
    return dist 
 
# Disparityを計算
df["disparity"] = df.apply(lambda x : cm_disparity(x["Lx"], x["Rx"]), axis=1)

# dispを計算
df['distance(z)'] = df['disparity'].apply(dist_formula)


# disparity と dipthの関係図をplot

fig, ax = plt.subplots()
x = np.array(df['disparity'])
y = np.array(df['distance(z)'])
ax.plot(x, y, label="test")
ax.set_xlabel('disparity')
ax.set_ylabel('distance(z)')
plt.show()

計測値

disparityとdipthの関係図

disparityとdepthが上手く反比例してる。
物体検出のbboxの座標からでも十分正確なdepthの距離が求められることがわかった。


参考サイト

webカメラ2台で距離測定その2