web-dev-qa-db-ja.com

PythonおよびOpenCV-車線検出アルゴリズムの改善

ビデオから車線を検出する必要があります。これが私のやり方です。

  1. 画像をスライスして関心領域(ROI)を決定します(中央部分に焦点を合わせます)
  2. ROIのグレースケール
  3. グレースケールされたROIをcv2.equalizeHistで均等化
  4. (3)にガウスぼかしを適用する
  5. cv2.adaptiveThresholdを使用したしきい値(4)
  6. skimage.morphology.skeletonizeを使用してスケルトン化(5)
  7. (6)にcv2.HoughLinesを適用します

cv2.HoughLinesについては、次のように設定しました。

  1. rhoが正の場合(つまり、直線が右に傾斜している(ボトムアップ)場合、特定の角度にある場合にのみ線が描画されます(角度の範囲を設定します))。
  2. rhoが負の場合(直線が左(下から上)に傾斜している場合、特定の角度にある場合にのみ線が描画されます)

これは線を引くための私のコードです:

lines = cv2.HoughLines(image_bin, 1, np.pi/180, 50)
    try:
        range = lines.shape[0]
    except AttributeError:
        range = 0

    for i in xrange(range):
        for rho, theta in lines[i]:
            if rho > 0 and (np.pi*1/10 < theta < np.pi*4/10):
                a = np.cos(theta)
                b = np.sin(theta)
                x0 = a * rho
                y0 = b * rho
                x1 = int(x0 + 1000 * (-b))
                y1 = int(y0 + 1000 * (a))
                x2 = int(x0 - 1000 * (-b))
                y2 = int(y0 - 1000 * (a))

                cv2.line(roi, (x1, y1), (x2, y2), (0, 255, 0))

            if rho < 0 and (np.pi*7/10 < theta < np.pi*9/10):
                a = np.cos(theta)
                b = np.sin(theta)
                x0 = a * rho
                y0 = b * rho
                x1 = int(x0 + 1000 * (-b))
                y1 = int(y0 + 1000 * (a))
                x2 = int(x0 - 1000 * (-b))
                y2 = int(y0 - 1000 * (a))

                cv2.line(roi, (x1, y1), (x2, y2), (0, 255, 0))

上記のcv2.HoughLines関数で行ったことを行わなかった場合、不要な線がたくさん描画されると思います。

パラメータなどを調整したところ、かなり良い結果が得られましたが、それはたった1枚の写真です。変化し続けるビデオにとってはそれほど良いことではないと思います。私が最も気になるのは、必要な線(つまり車線)を描くためのアルゴリズムについてです。より良い方法はありますか?少なくとも私のよりはましだ。

これは私の結果です:

元の画像: The original image

ROIの均等化されたヒストグラム、しきい値処理、およびスケルトン化された画像: Equalized Histogram, thresholded, and skeletonized

最終結果: - Final result

12
Hilman

アプリケーションに確率的ハフライン変換を使用することを検討することをお勧めします。 OpenCVのPython APIでは、関数cv2.HoughLinesPに実装されています。これにより、実際に線分が得られるため、エンドポイントを計算する必要がありません。また、標準のハフライン変換。

ただし、いくつかのトレードオフがあります。たとえば、線分をつなぎ合わせるロジックを追加する必要がある場合があります。一方で、それはそれほど悪いことではないことがわかりました。私のおもちゃプロジェクトの1つ(自動運転ミニチュアバス)は、このアプローチを使用し、別々の線分をつなぎ合わせると、標準のハフライン変換でラインがまったく得られないカーブした道路を扱いやすくなりました。 。

お役に立てば幸いです。

編集:線分の「ステッチ」の詳細に関しては、それはあなたが達成しようとしていることによって異なります。道路を表示したいだけで、線分の間にギャップがあることに満足している場合は、ステッチを行う必要はありません。すべての線分を表示するだけです。私のアプリケーションでは、車線の曲率を決定する必要があったので、車線の平均勾配を含む各道路車線のモデルを構築するためにいくつかのステッチを行いました。これは、車線の制御を担当するモジュールへの入力として使用されました。それに応じて車輪を動かすためのサーボ。

「ステッチ」とは、特に洗練されたものを意味するものではありませんが、それを実現するための特定のOpenCV機能を認識していません。同じ車線の一部である線分を関連付ける方法が必要でした。そこで、画像の上部から下に向かってHoughLinesPから返された線分を処理し、各線分の傾きとy切片を使用して、線分が交差する場所を決定しました。

6
Aenimated1