社会人研究者が色々頑張るブログ

pythonで画像処理やパターン認識をやっていきます

Python+OpenCVによる白線検出(3)

はじめにのはじめに

完成版の記事です nsr-9.hatenablog.jp

はじめに

nsr-9.hatenablog.jp

nsr-9.hatenablog.jp

これの続きです。 今回は、生成した白線(と消失点)の候補に関する仮説検証部分を実装します。
f:id:nsr_9:20210816155356p:plain

Verification

Verificationでは以下の2つを検証します。
1.2本の白線候補の式が尤もらしいか検証する「白線の検証」
2.2本の白線からなる消失点候補が尤もらしいか検証する「消失点の検証」
今回は白線の検証を実装しました。

白線の検証

白線の仮説生成では、左右でそれぞれ3点の白線候補点を生成し、真ん中以外の2点を通る直線を生成しました。
以下の図の様に、P1, P2, P3が正しく白線の候補点に位置する場合、P1とP3を通る直線上にP2が存在します。

f:id:nsr_9:20210816161246p:plain

しかしながら、P1, P2, P3が白線の候補点でない場合、直線上にP2は存在しません。
f:id:nsr_9:20210816161633p:plain

本論文ではこの性質を利用し、「直線とP2の距離が一定のしきい値以下の時、白線を正しく検出できている」と判断しています。   f:id:nsr_9:20210816161819p:plain

import cv2
import numpy as np
from straight_line import linear, calc_straight

def distance(p1, p2, p3):
    a, b = linear(p1, p3)
    return abs(a*p2[0]-p2[1]+b)/(a**2+1)**0.5

論文では直線の公式の近似式を用いていたのですが、今回は直線の距離の公式を愚直に実装しました。
linear関数とcalc_straight関数の詳細に関しては以前の記事を参照してください。

nsr-9.hatenablog.jp

必要な部分だけ抜粋すると次のようになります。

import cv2
import numpy as np


def linear(n1, n2):
    a = (n2[1]-n1[1])/(n2[0]-n1[0])
    b = (n2[0]*n1[1]-n1[0]*n2[1])/(n2[0]-n1[0])
    return a, b


def cross_point(n1, n2, m1, m2):
    a1, b1 = linear(n1, n2)
    a2, b2 = linear(m1, m2)
    
    if a1 == a2:
        return None, None
    return (b2-b1)/(a1-a2), (a1*b2-b1*a2)/(a1-a2)


def calc_straight(img, n1, n2):
    top = [[0, 0], [img.shape[1], 0]]
    btm = [[0, img.shape[0]], [img.shape[1], img.shape[0]]]

    tp = cross_point(n1, n2, top[0], top[1])
    bp = cross_point(n1, n2, btm[0], btm[1])

    tp = list(map(int, tp))
    bp = list(map(int, bp))
    print(tp[0], tp[1])
    
    return tp, bp 

実行例を以下に示します

f:id:nsr_9:20210816164207j:plain f:id:nsr_9:20210816164215j:plain
f:id:nsr_9:20210816164224j:plain f:id:nsr_9:20210816164243j:plain

青い2つの点が直線をなすP1とP3で、赤い点が距離を求めるP2になります。
この画像をGimp等の画像編集ソフトで開き、P2と直線のピクセル数を数えると、正しい距離が求まっている事が確認できます。

白線の仮説検証はこの直線と点の距離に対し、しきい値を用いることで行います。

def verification(p1, p2, p3, th):
    return True if distance(p1, p2, p3) < th else False

白線の仮説検証の動作例

今回作成した白線の仮説検証と、前回の白線検出を組み合わせて実行してみました。
実行結果の中から特徴的なフレームをピックアップしたので、以下に示します。

出力例
frame 17
f:id:nsr_9:20210816172957j:plain
frame 59
f:id:nsr_9:20210816173007j:plain
frame 132
f:id:nsr_9:20210816173016j:plain

左側に左右の白線の検証結果を可視化しています。
概ね直感通りの結果になっているように思えます。
frame 17の様に、まだ白線候補点の検出が安定していないフレームだとしきい値処理によってNGが返されています。
frame 59は白線検出が安定しているフレームです。両方の白線に対してOKが返されています。
frame 132は右側に車両が大きく移動したフレームです。左の白線が破線であることも相まって白線の候補点がズレているように見えるのですが、仮説検証により正しくNGが返されています。

まとめ

今回は、 An Efficient Lane Detection Algorithm For Lane Departure Detectionの白線のVerification部分を実装しました。
次は消失点のVerification部分を実装する予定です。

最後に動画化した実行結果を載せます。
f:id:nsr_9:20210816174944g:plain

f:id:nsr_9:20210816175010g:plain