OpenCV ~ 曲線検出

あらゆる運転シナリオにおいて、車線区分線は交通の流れと車両が走行すべき場所を示す重要な部分です。また、自動運転車の開発の出発点としても最適です。以前の車線検出プロジェクトを基にして、より効果的に動作し、困難な環境に対してより堅牢な曲線車線検出システムを実装しました。車線検出システムは、OpenCV ライブラリを使用して Python で作成されています。

実装手順は次のとおりです。

  • 歪み補正

  • 視点変換

  • ソーベルフィルター

  • ヒストグラムのピーク検出

  • スライディングウィンドウ検索

  • カーブフィッティング

  • カバレッジ検出レーン

  • ビデオに適用する

歪み補正

カメラのレンズは、入ってくる光を歪ませてカメラのセンサーに焦点を合わせます。これらは環境の画像をキャプチャするのに最適ですが、光がわずかに不正確に歪んでしまう傾向があります。これにより、コンピュータ ビジョン アプリケーションでの測定が不正確になる可能性があります。ただし、この歪みは簡単に修正できます。

チェッカーボードを使用してカメラを調整し、歪みを補正できます。

テスト ビデオで使用されるカメラは、歪みモデルの生成に使用されるチェッカーボードの写真を 20 枚撮影するために使用されます。まず画像をグレースケールに変換し、次に cv2.findChessboardCorners() 関数を適用します。チェス盤が直線のみからなる 2D オブジェクトであることはすでにわかっているため、検出された角にいくつかの変換を適用して正しく位置を揃えることができます。cv2.CalibrateCamera() を使用して、歪み係数とカメラ行列を取得します。カメラは校正済みです!

その後、 cv2.undistort() を使用して、残りの入力データの歪みを解除できます。以下に、チェッカーボードの元のイメージと修正されたイメージの違いを示します。

実装コード:

def undistort_img():
    # Prepare object points 0,0,0 ... 8,5,0
    obj_pts = np.zeros((6*9,3), np.float32)
    obj_pts[:,:2] = np.mgrid[0:9, 0:6].T.reshape(-1,2)
    # Stores all object points & img points from all images
    objpoints = []
    imgpoints = []
    # Get directory for all calibration images
    images = glob.glob('camera_cal/*.jpg')
    for indx, fname in enumerate(images):
        img = cv2.imread(fname)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        ret, corners = cv2.findChessboardCorners(gray, (9,6), None)
        if ret == True:
            objpoints.append(obj_pts)
            imgpoints.append(corners)
    # Test undistortion on img
    img_size = (img.shape[1], img.shape[0])
    # Calibrate camera
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size, None,None)
    dst = cv2.undistort(img, mtx, dist, None, mtx)
    # Save camera calibration for later use
    dist_pickle = {}
    dist_pickle['mtx'] = mtx
    dist_pickle['dist'] = dist
    pickle.dump( dist_pickle, open('camera_cal/cal_pickle.p', 'wb') )
def undistort(img, cal_dir='camera_cal/cal_pickle.p'):
    #cv2.imwrite('camera_cal/test_cal.jpg', dst)
    with open(cal_dir, mode='rb') as f:
        file = pickle.load(f)    mtx = file['mtx']
    dist = file['dist']
    dst = cv2.undistort(img, mtx, dist, None, mtx)
    return dst
undistort_img()
img = cv2.imread('camera_cal/calibration1.jpg')
dst = undistort(img) # Undistorted image

道路画像に適用される歪み補正です。微妙な違いには気づかないかもしれませんが、画像処理に大きな影響を与える可能性があります。

視点変換

カメラ空間内でカーブした車線を検出することは簡単ではありません。私道の鳥瞰図が必要な場合はどうすればよいでしょうか? これは、画像に透視変換を適用することで実行できます。以下にその様子を示します。 

何か気づきましたか?レーンが平らな 2D 表面上にあると仮定することで、レーン空間内のレーンを正確に表す多項式を当てはめることができます。それはクールじゃないですか?

cv2.getPerspectiveTransform() 関数を使用して変換行列を取得し、 cv2.warpPerspective() を使用してそれを画像に適用すると、これらの変換を任意の画像に適用できます。コードは次のとおりです。

def perspective_warp(img,
                     dst_size=(1280,720),
                     src=np.float32([(0.43,0.65),(0.58,0.65),(0.1,1),(1,1)]),
                     dst=np.float32([(0,0), (1, 0), (0,1), (1,1)])):
    img_size = np.float32([(img.shape[1],img.shape[0])])
    src = src* img_size
    # For destination points, I'm arbitrarily choosing some points to be
    # a nice fit for displaying our warped result
    # again, not exact, but close enough for our purposes
    dst = dst * np.float32(dst_size)
    # Given src and dst points, calculate the perspective transform matrix
    M = cv2.getPerspectiveTransform(src, dst)
    # Warp the image using OpenCV warpPerspective()
    warped = cv2.warpPerspective(img, M, dst_size)
    return warped
ソーベルフィルター

以前のバージョンでは、色を使用して車線の境界線を除外していました。ただし、これが常に最良の選択肢であるとは限りません。道路がアスファルトではなく明るい色のコンクリートを使用している場合、道路はカラーフィルターを簡単に通過し、パイプラインは道路を白い車線として認識しますが、これは堅牢ではありません。

代わりに、エッジ検出器に似たものを使用して、今回は道路をフィルタリングします。車線の境界線は通常、道路に対してコントラストが高いため、これを利用できます。前のバージョン 1 で使用されていた Canny エッジ検出器は、Sobel オペレーターを利用して画像関数の勾配を取得しました。OpenCV のドキュメントには、OpenCV の動作方法が詳しく説明されています。これを使用して高コントラスト領域を検出し、車線区分線をフィルタリングし、道路を無視します。

今度は彩度と明度の変化を検出するために、HLS 色空間を再度使用します。sobel オペレータがこれら 2 つのチャネルに適用され、x 軸に関する勾配を抽出し、勾配しきい値を通過したピクセルを画像内のピクセルを表すバイナリ マトリックスに追加します。カメラ空間とレーン空間では次のようになります。

カメラから遠い画像部分は品質が十分に維持されないことに注意してください。より遠くにある物体からのデータは、カメラの解像度制限により非常にぼやけてノイズが多くなります。画像全体に注目する必要はないので、画像の一部だけを使用することもできます。使用する画像 (ROI) は次のようになります。 

ヒストグラムのピーク検出

スライディング ウィンドウ アルゴリズムと呼ばれる特別なアルゴリズムを適用して車線境界線を検出します。ただし、適用する前に、アルゴリズムの適切な開始点を決定する必要があります。レーン ピクセルがある場所から開始すれば問題なく動作しますが、そもそもレーン ピクセルがどこにあるかをどのように検出するのでしょうか? 実はとても簡単なんです!

x 軸に関する画像のヒストグラムを取得します。以下のヒストグラムの各セクションは、画像の各列にある白いピクセルの数を示します。次に、画像の両側で最も高いピークを車線の境界線ごとに 1 つずつ取得します。バイナリ イメージの隣にあるヒストグラムは次のようになります。

 

 

スライディングウィンドウ検索

スライディング ウィンドウ アルゴリズムを使用して左右の車線の境界を区別し、車線の境界を表す 2 つの異なる曲線を当てはめることができます。

アルゴリズム自体は非常にシンプルです。最初のウィンドウは、初期位置から開始して、ウィンドウ内のピクセル数を測定します。ピクセル数が特定のしきい値に達すると、次のウィンドウが検出されたピクセルの平均横位置に移動します。十分なピクセルが検出されない場合、次のウィンドウは同じ水平位置から始まります。これは、ウィンドウが画像のもう一方の端に到達するまで続きます。

ウィンドウ内に収まるピクセルにはフラグが割り当てられます。以下の画像では、青でマークされたピクセルが右車線を表し、赤でマークされたピクセルが左車線を表します。

カーブフィッティング

プロジェクトの残りの部分は非常に簡単です。np.polyfit() を使用して赤と青のピクセルにそれぞれ多項式回帰を適用すると、検出器は完了です。ワオソフト アイオット http://143ai.com

曲線は次のようになります。

検出レーンの描画

これは検出システムの最後の部分、つまりユーザー インターフェイスです。レーンの検出された部分を埋めるオーバーレイを作成するだけで、最終的にビデオに適用できます。ビデオ検出に適用すると、次の出力が表示されるはずです。

結論は

以上が、基本的な曲線車線検出器です。以前のバージョンよりもはるかに優れており、カーブした私道でも処理できます。ただし、依然として影や道路のテクスチャの急激な変化に多少悩まされています。次の車線検出プロジェクトでは、いくつかの機械学習技術を使用して、非常に堅牢な車線および車両検出システムを開発します。ありがとうございます!

完全なコード:  https://github.com/kemfic/Curved-Lane-Lines/blob/master/P4.ipynb

参考リンク:  https://www.hackster.io/kemfic/curved-lane-detection-34f771

おすすめ

転載: blog.csdn.net/qq_29788741/article/details/131354881