2022年3月13日の投稿PiCar-Xでlane detection(01) はじまりから数回にわたって、車が進むべき方向を決めるのに、道路写真をどのように処理して必要な情報を抽出するかについて書きました。
今回Mindstorms EV3で同じくLane Detectionを行うのに、OpenCVのコーナー検出を使ってみようと思います。
OpenCVのコーナー検出について参考にしてたのは下記資料です。
OpenCVを用いた画像のコーナー検出
from PIL import Image
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
本記事で使用する画像は黒色背景に白色で右曲がりのカーブが描かれた画像です。
image = cv2.imread("code-05.png")
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
画像の高さと幅の値を取得します。
# 画像の高さ 幅を取得
Image_height, Image_width, c = image.shape
print(image.shape)
(720, 1280, 3)
画像の上下をカットし中央の画像のみ使用します。
# 塗りつぶす色を作成
green = (0, 255, 0)
black = (0, 0, 0)
color = black
# オリジナル画像の上下を塗りつぶし
img_temp = cv2.rectangle(image, (0, 0), (Image_width, 200),color, thickness=-1)
img = cv2.rectangle(img_temp, (0, Image_height), (Image_width, Image_height-200), color, thickness=-1)
plt.imshow(img)
plt.show()
コーナー検出¶
以下の説明資料は参考資料からの転写です。
コーナー検出にはcv2.goodFeaturesToTrack()を用います。cv2.goodFeaturesToTrack()は以下の様に用います。
cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance, blockSize=
***
, useHarrisDetector=***
, k=***
)
cv2.goodFeaturesToTrack()の引数は以下の表のようになります。
引数 | 内容 |
---|---|
image | 対象の画像 |
maxCorners | 検出するコーナーの最大数 |
qualityLeve | コーナーの最低限許容される品質を特徴付けるパラメータ。0~1の値 |
minDistance | 検出したコーナー間の最小のユークリッド距離 |
blockSize | 微分共分散行列を計算するための平均ブロックのサイズ |
useHarrisDetector Harris | 検出器を使用するかどうかを示すパラメーター |
k Harris | 検出器の自由パラメータ(Harris検出器を使用する場合) |
Harrs検出器を使いたい場合には、useHarrisDetector=Trueにし、kに値を設定してください。
本記事では、コーナー検出後にコーナーを赤い円で印をつけます。その円を描画するにはcv2.circle()を用います、cv2.circle()は以下の様に用います。
img = cv2.circle(img, center, radius, color, thickness)
cv2.circle()の引数は以下の表のようになります。
引数 | 内容 |
---|---|
img | 円を描画したい画像 |
center | 描画したい円の中心位置 |
radius | 描画したい円の半径 |
color | 描画したい円の色 |
thickness | 描画したい円の太さ。負の場合、中塗り。 |
それでは、cv2.goodFeaturesToTrack()を用いてコーナーを検出し、検出したコーナーにcv2.circle()で円を描画していきます。以下の例では、検出するコーナーの最大値は40、ブロックサイズは3、コーナーの検出品質パラメータは0.2、最小のユークリッド距離は5に設定してコーナーを検出し、検出したコーナーに半径6、太さ2、赤色の円を描画します。
#グレースケール化
img_gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
#コーナー検出
MAX_CORNERS = 40
BLOCK_SIZE = 3
QUALITY_LEVEL = 0.2
MIN_DISTANCE = 5
corners = cv2.goodFeaturesToTrack(img_gray,MAX_CORNERS,QUALITY_LEVEL,\
MIN_DISTANCE,blockSize=BLOCK_SIZE,useHarrisDetector=False)
corners = np.intp(corners)
#検出したコーナー位置に円を描画
for i in corners:
x,y=i.ravel()
cv2.circle(img,(x,y),6,(255,0,0),2)
plt.imshow(img)
plt.show()
検出したコーナーの位置データを表示して確認してみました。 ここでは理想的に4隅の4個のデータが検出されましたが、同じ個所の重複も含めて4個以上のデータが検出される場合もあります。 これは感度の問題なのでしょうけれども解決策はわかりません。
print("type of corners: ", type(corners))
print('')
print("shape of corners: ", corners.shape)
print('')
print("contents of corners: ")
print(corners)
type of corners: <class 'numpy.ndarray'> shape of corners: (4, 1, 2) contents of corners: [[[663 518]] [[669 201]] [[292 201]] [[292 519]]]
これらのコーナーの中心(平均)を計算します。
pxy = np.average(corners ,axis = 0)
px, py = pxy[0].astype(int)
# px, py = pxy[0]
print(px)
print(py)
479 359
コーナーの中心(平均)を緑色の〇で表示します。
cv2.circle(img,(px, py),6,(0,255,0),2)
plt.imshow(img)
plt.show()
中心位置が求まれば後は前回と同じ処理を行います。 この〇で表示したコーナーの中心(平均)が画面の中央に位置するように、すなわちEV3本体が白線の中央に位置するようにステアリングを操作すれば、常に白線を追随する自動運転を行うことが出来ます。
0 件のコメント:
コメントを投稿