LoginSignup
0
0

【OpenCV】作ってみる自動運転。車載カメラからの白線検出(二値化・Hough変換)

Last updated at Posted at 2023-02-19

はじめに

画像処理を学習する機会に恵まれたので、昨今話題の自動運転関係の遊びをやってみます。
白線などの誘導の目印になるものに沿って、車体を走らせるのが定番アイデアのようです。そのため、今回は白線を検出することを目指します。

今回のゴールは下図。
result.png
画像処理の流れは、3ステップ。
白線を直線として検出できないか?という定番の作戦です。

  • 入力画像をグレースケールに変換
  • グレースケール画像の二値化
  • 直線(線分)を検出する

コードを書いていく

Step0. 準備

Python 3.10.8、opencv 4.7.0を利用します。まずimportしていく。

import cv2
import numpy as np
from matplotlib import pyplot as plt

Step1. 入力画像をグレースケールに変換する

入力画像を読み込み、グレースケールに変換します。
(分析に活用するため、ヒストグラムも一応取得します)

# 画像の読み込み
img = cv2.imread("input_img.jpg")
# グレースケールに変換
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# ヒストグラムの取得
# 引数:入力画像、チャンネル指定、マスク画像(利用する場合)、BINの数、画素値の範囲[0〜256]
img_hist_cv = cv2.calcHist([gray_img], [0], None, [256], [0, 256])

Step2. 二値化

グレースケール画像を二値化します。白線を残していきます。

# 二値化する画素値のしきい値設定
thresh = 180

# 引数:グレースケール画像、しきい値、しきい値以上の画素に割り当てる値、処理内容。
# 返り値:retval、2値画像
# 判別分析法を利用しない場合は、retval = (入力したしきい値)
ret, bin_img = cv2.threshold(gray_img, thresh, 255, cv2.THRESH_BINARY)

Step3. Hough変換による、直線検出(線分検出)

白線は、画像中では直線(線分)とみなすことができるはずです。
直線(線分)の検出には、Hough変換を利用します。

# Hough変換による直線検出
# rho:投票空間の距離分解能
# theta:投票空間の角度分解能
# threshold : 直線とする投票数のしきい値
# minLineLength : 最小の線分の長さ
# maxLineGap : 2点が同一線分上にあるとみなす最大間隔
# 返り値は、線分情報(始点のxy座標、終点のxy座標の値)
lines = cv2.HoughLinesP(bin_img, rho=1, theta=np.pi/360, threshold=80, minLineLength=80, maxLineGap=1)

# 入力画像に検出した直線を赤線で引く。
for line in lines:
    x1, y1, x2, y2 = line[0]# lineの要素は座標配列[x1、y1、x2、y2]のみ
    red_lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 3)

Step4. 各処理結果を描画する

OpenCVは、画像のチャンネルを「BGR」として扱っています。一方、matplotlibは「RGB」で扱うことに注意が必要です。
えっ?色おかしくない?と何度もなりました。

# --- グレースケール ---
plt.subplot(321)
plt.imshow(cv2.cvtColor(gray_img, cv2.COLOR_BGR2RGB))
plt.title('Input image (Gray scale)')

# --- 二値化 ---
plt.subplot(323)
plt.imshow(cv2.cvtColor(bin_img, cv2.COLOR_BGR2RGB))
plt.title('Binary image')

# --- Hough変換 ---
plt.subplot(325)
plt.imshow(cv2.cvtColor(red_lines_img, cv2.COLOR_BGR2RGB))
plt.title('Hough transform')

# --- Histogram ---
plt.subplot(324)
plt.plot(img_hist_cv, label="histogram")
plt.axvline(x=ret,color='orange',linestyle='--', label="threshold") # しきい値はオレンジ色の破線で描画
plt.legend(fontsize=7)# 凡例の表示
plt.title('Histogram & Threshold')

plt.tight_layout()# 図やグラフ同士が重ならないようにする。
plt.savefig("result.png")# 出力結果を画像で保存する
plt.show()

おわりに

今回は白線を検出してみました。しかし、空やガードレールも直線(線分)として検出され、白線だけ綺麗に検出できませんでした。仮に誤検出した空に沿って走行した場合、すぐにガードレールに直撃してしまいますね。
入力画像やパラメーター設定など、工夫が必要だとわかりました。

(参考)入力画像には、写真素材ルーム様の素材を利用いたしました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0