曲がった車線の検出
ストーリー
はじめに
どのような運転シナリオでも、車線は交通の流れと車両の運転場所を示すための重要な要素です。自動運転車を開発する際の出発点としても適しています。以前の車線検出プロジェクトに基づいて、カーブした車線検出システムを実装しました。これは、はるかにうまく機能し、困難な環境に対してより堅牢です。
車線検出システムは、OpenCVライブラリを使用してPythonで作成されました。現在の画像処理パイプラインは次のとおりです。
- 歪み補正
- パースペクティブワープ
- Sobelフィルタリング
- ヒストグラムのピーク検出
- スライディングウィンドウサーチ
- カーブフィッティング
- オーバーレイ検出レーン
- ビデオに適用
以前のシステムの制限
以前の車線検出プロジェクトでは、画像内の直線の車線を検出できる非常にシンプルな車線検出システムを開発しました。完璧な条件下では適切に機能しましたが、湾曲した車線を正確に検出できず、障害物や影に対して堅牢ではありませんでした。このバージョンでは、これらの両方の制限が改善されています。
歪み補正
カメラレンズは、入ってくる光を歪ませてカメラセンサーに焦点を合わせます。これは、環境の画像をキャプチャするのに非常に役立ちますが、光がわずかに不正確に歪むことがよくあります。これにより、コンピュータビジョンアプリケーションでの測定が不正確になる可能性があります。ただし、この歪みは簡単に修正できます。
このオブジェクトは、多くの場合、以下のような非対称のチェッカーボードです。
キャリブレーションチェッカーボード(OpenCV Docs)
テストビデオで使用されたカメラは、歪みモデルの生成に使用されたチェッカーボードの20枚の写真を撮影するために使用されました。まず、画像をグレースケールに変換してから、cv2.findChessboardCorners()関数を適用します。このチェス盤は直線のみの2次元オブジェクトであることがすでにわかっているので、検出されたコーナーにいくつかの変換を適用して、それらを適切に位置合わせすることができます。 cv2.CalibrateCamera()を使用して、歪み係数とカメラ行列を取得しました。カメラが調整されました!
その後、cv2.uncompress()を使用して、残りの入力データを修正できます。チェッカーボードの元の画像と修正された画像の違いを以下に示します。
キャリブレーションチェッカーボードを含む画像に適用される歪み補正。
def unConstraint_img():
#オブジェクトポイントを準備します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)
#すべての画像のすべてのオブジェクトポイントとimgポイントを保存します
objpoints =[]
imgpoints =[]
#すべてのキャリブレーション画像のディレクトリを取得
images =glob.glob( 'camera_cal / *。jpg')
indx、fname in enumerate (画像):
img =cv2.imread(fname)
gray =cv2.cvtColor(img、cv2.COLOR_BGR2GRAY)
ret、corners =cv2.findChessboardCorners(gray、(9,6 )、なし)
if ret ==True:
objpoints.append(obj_pts)
imgpoints.append(corners)
#imgで歪みのないテスト
img_size =( img.shape [1]、img.shape [0])
#カメラのキャリブレーション
ret、mtx、dist、rvecs、tvecs =cv2.calibrateCamera(objpoints、imgpoints、img_size、None、None)
dst =cv2.uncompress(img、mtx、dist、None、mtx)
#後で使用するためにカメラのキャリブレーションを保存します
dist_pickle ={}
dist_pickle ['mtx'] =mtx
dist_pickle ['dist' ] =dist
pickle.dump(dist_pickle、open( 'camera_cal / cal_pickle.p'、 'wb'))
def uncompress(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.unConstraint(img、mtx、dist、None、mtx)
return dst
unConstraint_img()
img =cv2.imread( 'camera_cal / calibration1.jpg')
dst =unConstraint(img)#歪みのない画像
これらに使用される関数は、JupyterNotebookのコードにもあります。 セクション。
運転シーンに適用される歪み補正
パースペクティブワープ
パースペクティブワープ画像
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
#宛先ポイントについては、任意にいくつかのポイントを選択しています
#ワープした結果を表示するのに最適
#正確ではありませんが、目的には十分に近い
dst =dst * np.float32(dst_size)
#与えられたsrcポイントとdstポイント、パースペクティブ変換マトリックスを計算します
M =cv2.getPerspectiveTransform(src、dst)
#OpenCVを使用して画像をワープしますwarpPerspective()
warped =cv2.warpPerspective(img、M、dst_size)
ワープを返す
Sobelフィルタリング
以前のバージョンでは、色を使用して車線を除外していました。ただし、これが常に最良のオプションであるとは限りません。道路がアスファルトの代わりに明るい色のコンクリートを使用している場合、道路はカラーフィルターを簡単に通過し、パイプラインはそれを白い車線として認識します。良くない。
代わりに、エッジ検出器と同様の方法を使用して、今回は道路をフィルターで除外できます。車線は通常、道路とのコントラストが高いため、これを活用できます。 キャニー 以前にバージョン1で使用されていたエッジ検出器は、 Sobel Operator を使用します 画像関数の勾配を取得します。 OpenCVのドキュメントには、その仕組みに関するすばらしい説明があります。これを使用して、コントラストの高い領域を検出し、車線のマーキングをフィルタリングして道路を無視します。
今度は彩度と明度の変化を検出するために、HLS色空間を再び使用します。これらの2つのチャネルにソーベル演算子が適用され、x軸に関する勾配が抽出され、勾配しきい値を通過するピクセルが、画像内のピクセルを表すバイナリ行列に追加されます。カメラスペースとレーンスペースでは次のようになります。
ヒストグラムのピーク検出
スライディングと呼ばれる特別なアルゴリズムを適用します ウィンドウ アルゴリズム レーンラインを検出します。ただし、それを適用する前に、アルゴリズムの適切な開始点を決定する必要があります。レーンピクセルが存在する場所から開始するとうまく機能しますが、そもそもこれらのレーンピクセルの位置を検出するにはどうすればよいでしょうか。実はとても簡単です!
X軸に関する画像のヒストグラムを取得します。以下のヒストグラムの各部分は、画像の各列にある白いピクセルの数を示しています。次に、各レーンラインに1つずつ、画像の各側の最も高いピークを取得します。バイナリ画像の横にあるヒストグラムは次のようになります。
スライディングウィンドウサーチ
スライディングウィンドウアルゴリズムを使用して、左右の車線境界を区別し、車線境界を表す2つの異なる曲線を適合させることができます。
詳細を読む:曲がった車線の検出
製造プロセス