2022年5月16日月曜日

PiCar-Xでlane detection(06) 取得した道路情報から位置情報の計算

 「PiCar-Xでlane detection(02) 自動運転のための車線検出」で下図のように車線を検出することが出来ました。今回はここから車の進むべき方向を決める、道路の真ん中=道路の向きの中心を求める方法について考えてみます。


一般的にはここから左側の複数の線分(赤い領域)の平均を取って左車線、同じく右側の複数の線分(青い領域)の平均を取って右車線を求めて、その両線の中央値を計算して道路の中央を求めます。


ただ、これが意外とややっこしい(-.-;)

真ん中から左の線分を左車線、同じく右側の線分を右車線としたいところですが、例えば下の写真のように必ずしも車は常に道路の中央からPiCameraで写真を撮っているわけではなく、カーブなどでは右に左にステアリングをとっているので、道路に対して斜めからの写真も多くなります。下の図のように片方の車線が画面からはみ出しそうになることも再々です。


この場合、右側車線の上端も写真中央から左側に位置しており、真ん中で左右を分けようとすると全て左側車線と判断されてします。または、道路は上図のように「ハの字」に映っているから、右に傾いている線分を左側車線、左に傾いている線分を右側車線と考えたい所ですが、カーブなどではすべて右に傾いたり、全て左に傾いたりすることも良くあります。
とにかく左側車線と右側車線の区分をすることが出来ず、どのように左右を分けたら良いのか悩むところです。

そこで参考とした資料で行っていた左右の車線を検出することを諦めて、「PiCar-Xでlane detection(01)」では道路の中央に黄色い線を追加し、この黄色い線を追随するようプログラムに変更しました。

以下「PiCar-Xでlane detection(01)」に掲載したプログラムに沿って、今までの説明と話がダブってしまいますが、その動きを見てみたいと思います。デモ画像として「PiCar-Xでlane detection(01)」で走らせたモデルコースと同じ配色の

を使って、処理の流れを見ていきます。

1.PiCameraから画像の取り込み

「PiCar-Xでlane detection(04) PiCameraから画像の取り込み」で説明したように、imutilsのVideoStreamを使って動画撮影➡画像の切取りを行っています。

# 画像の高さ 幅を取得
Image_height, Image_width, c = image.shape

    Image_height:  480
    Image_width:  640


2.オリジナル画像から作業領域をクロップ

cropped_image = image[int(Image_height / 2):int(Image_height / 2 + 100), 0:int(Image_width)]

画像の高さは、中央から下へ幅100pix、横幅は画像の幅そのままでクロップ


3.画像をBGRからHSVへ変換

hsv_image = cv2.cvtColor(cropped_image, cv2.COLOR_BGR2HSV)


4.OpenCV – inRangeで画像を2値化

lower = np.array([20, 0, 0])
upper = np.array([40, 255, 255])
masked_image = cv2.inRange(hsv_image, lower, upper)


5.OpenCV – cannyによるエッジ検出

canny_conversion = cv2.Canny(masked_image, 50, 155)


6.region of interest(注目する領域)を設定

ROI_image = reg_of_interest(canny_conversion)

見た目は変化ありませんが、「PiCar-Xでlane detection(05) PiCameraで撮影した画像の切り取りについて」で説明したように左右を台形状にカットしています。


7.OpenCV – HoughLinesPによる直線の検出

Hough_lines = cv2.HoughLinesP(ROI_image, 2, np.pi / 180, 50, np.array([]), minLineLength=20, maxLineGap=20)

# Hough_linesをcropped_imageと同じ大きさの黒色のキャンパスに描画
lanelines_image = show_lines(cropped_image, Hough_lines)


【それに続く処理】

黄色い線の左右両端を検出しているので、この例では左右2本の線分が検出されています。ただこの例でも左側がやや短く検出されています。また撮影条件によっては線分が途中で途切れたりして2本以上の線分として検出されるケースもあります。このブログページの最初の画像がそのよい例だと思います。
これらの複数の線分から左端・右端の線分を求めます。

left_right_lines = line_select(lanelines_image, Hough_lines)

# left-right_linesをcropped_imageと同じ大きさの黒色のキャンパスに描画
line_image = show_lines_result(cropped_image, left_right_lines)


# 上のline_imageとcropped_imageとを合成
combine_image = cv2.addWeighted(cropped_image, 0.8, line_image, 1, 1)



left_right_linesの中身は、

    array([[313, 100, 307,   0], 
              [341, 100, 335,   0]])

2本の線分のデータとなっています。


プログラムでは、最終的に上のcombine_imageに左右両線の上端の数値データを付け加えた画像を保存しています。



line_select関数で、Hough変換で得られた複数の線分の一番左の線分と一番右側の線分を取得していますが、それ以外にも
●垂直な線分はmake_coordinates関数の計算でエラーとなるので、作為的に2pixをプラスしている
●線分の下端位置が30pixに満たない線分は、イレギュラーなデータとして除く
といった処理も行っています。


このleft_right_linesのデータを使って、左右両線分の上端の平均(道路の中央)を求め、この平均(道路の中央)が画面の中央値(Image_width/2)に位置するように舵を切ります。

# left_line_top
left_line_top = left_right_lines[0, 2]

# right_line_top
right_line_top = left_right_lines[1, 2]

center_line = (left_line_top + right_line_top) / 2

# image_center
image_center = Image_width / 2

# -----------------------------------------------------------------------------
# steer
steer = (center_line - image_center) / image_center * 80
sterrは、  
px.set_dir_servo_angle(steer)で使う前輪を何度回転させるかの数値で、  
steer=(center_line-image_center)/image_center×80  
の式で画面の中央から大きくズレているときは大きく、ズレが小さいときは小さく舵を切るように制御しています。
上の式の「80」は、実際に動かしながら試行錯誤で求めた(ハイパー)パラメーターで、モデル条件が変われば改めて試行錯誤で最適解を求め直す必要があります。

2022年5月6日金曜日

PiCar-Xでlane detection(05) PiCameraで撮影した画像の切り取りについて

 今回は、手順の2番目と6番目についてです。

1.PiCameraから画像の取り込み

2.オリジナル画像から作業領域をクロップ

3.画像をBGRからHSVへ変換

4.OpenCV – inRangeで画像を2値化

5.OpenCV – cannyによるエッジ検出

6.region of interest(注目する領域)を設定

7.OpenCV – HoughLinesPによる直線の検出


私の環境でPiCameraで撮影したオリジナルの画像は例えば下の写真のようになっています。




私たちが必要としているのは、これから車が進むであろう写真中央部の道路の位置情報(中央はどのあたりか?)ですから、写真上部はこの後の作業には要らない部分であり、そればかりか後の作業で不要な線分を拾ったりして、多くのノイズを発生させる原因ともなり得ます。また足元に近い部分も不要になりますので、必要と思われる部分だけを切り取ることにしました。これが2番目の操作です。


        # オリジナル画像から作業領域をクロップ
        cropped_image = image[int(Image_height/2):int(Image_height/2+100), 0:int(Image_width)]

画面中央の高さから100ピクセルほどの高さの画像を切り取っています。

さらに少しでもノイズを拾わないために、下の画像のピンク色の台形で囲った部分だけを以下の処理に使うことにしました。これが6番目の操作です。


def reg_of_interest(image):
          Image_height = image.shape[0]
          Image_width = image.shape[1]
          polygons = np.array([[(100, 0),(0, Image_height), (Image_width-40,Image_height), (Image_width-100, 0)]])
          image_mask = np.zeros_like(image)
          cv2.fillPoly(image_mask, np.int32([polygons]), 255)
          masking_image = cv2.bitwise_and(image,image_mask)
          return masking_image

切り取る台形の形は適当に決めています。

これで画像データの前処理は終了です。次回は最終回、その画像から中央の位置を数値化します。

今回、カメラで撮った写真を元にライントレースして、PiCar-Xを自動走行させていますが参考テキストそのままでは上手くいきません。参考テキストでの走行環境、私の走行環境、その他の環境で条件パラメーター(いわゆるハイパーパラメーター)を変えていかないと上手く動かないようです。




2022年4月23日土曜日

PiCar-Xでlane detection(04) PiCameraから画像の取り込み

 今回は、手順1番目のPiCameraから画像の取り込みについてです。

1.PiCameraから画像の取り込み

2.オリジナル画像から作業領域をクロップ

3.画像をBGRからHSVへ変換

4.OpenCV – inRangeで画像を2値化

5.OpenCV – cannyによるエッジ検出

6.region of interest(注目する領域)を設定

7.OpenCV – HoughLinesPによる直線の検出


一般的にpythonからPicameraを制御するためにはpicameraパッケージを使います。

【プログラム例】

import time
import picamera

# 写真の保存場所
CAM_DIR = "/home/pi/picar-x/Picamera/"

with picamera.PiCamera() as camera:


 while True:
   try:
     camera.resolution = (640, 480)     
     camera.start_preview()
     time.sleep(2)
     filename = time.strftime("%Y%m%d%H%M%S") + ".jpg"
     save_dir_filename = CAM_DIR + filename
     camera.capture(save_dir_filename)
   except KeyboardInterrupt:
     print("Ctrl+Cで停止しました")
     break
しかしここでは、画像・動画に関する処理機能をまとめたOpenCVライブラリと、画像処理ユーティリティーのimutilsモジュールをそれぞれインストールして使いました。

pip install opencv-contrib-python
pip install imutils

【プログラム例】
import cv2
import time
from imutils.video import VideoStream
from imutils import resize

# 写真の保存場所
CAM_DIR = "/home/pi/picar-x/Picamera/"

vs = VideoStream(src=0).start()

while True:
    try:
       # ファイルの取込
       img = vs.read()
       image = resize(img, width=640)

        
       filename = time.strftime("%Y%m%d%H%M%S") + ".jpg"
       save_dir_filename = CAM_DIR + filename
       cv2.imwrite(save_dir_filename,image)

    except KeyboardInterrupt:
      print("Ctrl+Cで停止しました")
      break

2022年4月4日月曜日

PiCar-Xでlane detection(03) OpenCVで画像の特定の色を抽出する

 前回の方法で車線を検出することが出来ましたが、白線も黄線も一緒に検出してしまいました。別に一緒に検出してダメなわけは無いのですが、注目している欲しい線分だけではなくその他の不要な線分も検出してしまうという事で、セレクトして線分を検出できればより質の高い前処理になると思います。

今回の注目点は、手順の3と4番目です。

1.PiCameraから画像の取り込み

2.オリジナル画像から作業領域をクロップ

3.画像をBGRからHSVへ変換

4.OpenCV – inRangeで画像を2値化

5.OpenCV – cannyによるエッジ検出

6.region of interest(注目する領域)を設定

7.OpenCV – HoughLinesPによる直線の検出

特定の色の抽出は2段階で行います。まず画像で使用されている色空間のRGB(OpenCVではBGRの順)をHSV色空間に変換します。これはRGB画像では光(照明)の影響を受けて同じ色でも濃い色・淡い色などの異なった色で表示されてしまう可能性がありますが、HSV色空間ではその影響を受けにくい為のようです。

その後inRange関数で画像を2値変換し、指定した特定の画素を抽出します。

OpenCVを使った色の抽出はネットにも沢山説明が載っていますので参考にしてください。

前回の『PiCar-Xでlane detection(02) 自動運転のための車線検出』のプログラムに必要な部分を追加して色の抽出を行ってみます。使用したのは以下の図です。


まず前回のプログラムそのままを使って処理を行ってみると

グレー変換


ノイズ除去のための平滑化

edgesの検出

Hough変換で直線の検出

予想したとおり全ての色の線が検出されました。

ここからは、特定の色抽出を行ってみます。

まずHSV色空間への変更
# HSV color space
image4 = cv2.cvtColor(image1, cv2.COLOR_BGR2HSV))

全く異なった色になってしまいました。これがHSV色空間というものなのですかね。良く分かりません。

つぎにinRange関数による画像の2値変換
inRange関数で画像を2値変換するのでグレー変換は削除しました。

# 色の抽出
# 黄色
lower = np.array([10, 100, 100])
upper = np.array([30, 255, 255])
# 白色
# lower = np.array([0, 0, 100])
# upper = np.array([180, 45, 255])
image_mask = cv2.inRange(image_blur, lower, upper)

黄色の線のみが残っています。

edges検出

Hogh変換による直線の検出

期待したとおりに黄色の線のみが検出できました。

全体のプログラムを掲載しておきます。
import cv2
import numpy as np

def img_show(image, text):
  img_resize = cv2.resize(image, (640, 480))
  cv2.imshow(text, img_resize)
  cv2.waitKey(0)
  cv2.destroyAllWindows()

def show_lines(image, lines):
          lanelines_image = np.zeros_like(image)
          if lines is not None:
            for line in lines:
              X1, Y1, X2, Y2 = line.reshape(4)
              cv2.line(lanelines_image, (X1, Y1), (X2, Y2), (0,255,0), 2)
          return lanelines_image
  
#画像の読み込み
image_path = 'input_dir/color.png'
image = cv2.imread(image_path)
img_show(image, 'original')

# HSV color space
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
img_show(image_hsv, 'hsv')
cv2.imwrite('output_dir/image_hsv.png', image_hsv)

# Gaussian blur
# 画像のぼかして平滑化することで、画像中のノイズ除去を行います
image_blur = cv2.GaussianBlur(image_hsv, (5,5), 0) 
img_show(image_blur, 'blur')
cv2.imwrite('output_dir/image_blur.png', image_blur)

# 色の抽出
# 黄色
lower = np.array([10, 100, 100])
upper = np.array([30, 255, 255])
# 白色
# lower = np.array([0, 0, 100])
# upper = np.array([180, 45, 255])
image_mask = cv2.inRange(image_blur, lower, upper)
img_show(image_mask, 'mask')
cv2.imwrite('output_dir/image_mask.png', image_mask)

#edgesの検出
image_edges = cv2.Canny(image_mask,50,150)
img_show(image_edges, 'edges')
cv2.imwrite('output_dir/image_edges.png', image_edges)

#Hough変換による直線の検出
hough_lines = cv2.HoughLinesP(image_edges, 2, np.pi/180, 200, np.array([]), minLineLength= 10, maxLineGap=50)

image_lanelines = show_lines(image, hough_lines)

img_show(image_lanelines,'Hough lines')
cv2.imwrite('output_dir/image_lanelines.png', image_lanelines)

2022年3月22日火曜日

PiCar-Xでlane detection(02) 自動運転のための車線検出

 車(PiCar-X)を決められたコース(道路)に沿って走らせるためには、当然PiCameraで写した写真からコースの向かっている方向を読み取り、進むべき方法をコンピュータ(RaspberryPi)に教えなければなりません。その為にはまず車線を線分として検出する必要があります。

【道路の画像】




その手順が前回書いた

1.PiCameraから画像の取り込み

2.オリジナル画像から作業領域をクロップ

3.画像をBGRからHSVへ変換

4.OpenCV – inRangeで画像を2値化

5.OpenCV – cannyによるエッジ検出

6.region of interest(注目する領域)を設定

7.OpenCV – HoughLinesPによる直線の検出

です。

まず順番は無視して、Canny法でエッジ検出をしてHough変換で直線を見つけてみます。
Canny法を使うために、はじめに画像をグレー変換し、ノイズ除去のために平滑化を行いました。

道路の画像として下記の絵に描いた図を使用しました。黄色と白色の車線があります。

グレー変換から
#画像の読み込み
image_path = 'road_image.png'
image = cv2.imread(image_path)

#gray scale
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

つづいてノイズ除去のための平滑化
# Gaussian blur
# 画像のぼかして平滑化することで、画像中のノイズ除去を行います
image_blur = cv2.GaussianBlur(image_gray, (5,5), 0)

Canny法によるedges検出
#edgesの検出
image_edges = cv2.Canny(image_blur,50,150)

Canny法のパラメーターの調整方法はここが解りやすいと思います。

Hough法による直線の検出
#Hough変換による直線の検出
hough_lines = cv2.HoughLinesP(image_edges, 2, np.pi/180, 200, np.array([]), minLineLength= 10, maxLineGap=50)

取りあえず白線、黄線のラインは緑色の複数の線として検出できています。
白線と黄線を別々に検出できれば応用範囲が広がりそうです。
そのためのステップが今回飛ばした3~4番目です。
今日はここまで、プログラム全体を下記に載せておきます。
import cv2
import numpy as np

def img_show(image, text):
  img_resize = cv2.resize(image, (640, 480))
  cv2.imshow(text, img_resize)
  cv2.waitKey(0)
  cv2.destroyAllWindows()

def show_lines(image, lines):
          lanelines_image = np.zeros_like(image)
          if lines is not None:
            for line in lines:
              X1, Y1, X2, Y2 = line.reshape(4)
              cv2.line(lanelines_image, (X1, Y1), (X2, Y2), (0,255,0), 2)
          return lanelines_image
  
#画像の読み込み
image_path = 'road_image.png'
image = cv2.imread(image_path)
img_show(image, 'original')

#gray scale
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
img_show(image_gray, 'gray')
cv2.imwrite('image_gray.png', image_gray)

# Gaussian blur
# 画像のぼかして平滑化することで、画像中のノイズ除去を行います
image_blur = cv2.GaussianBlur(image_gray, (5,5), 0) 
img_show(image_blur, 'blur')
cv2.imwrite('image_blur.png', image_blur)

#edgesの検出
image_edges = cv2.Canny(image_blur,50,150)
img_show(image_edges, 'edges')
cv2.imwrite('image_edges.png', image_edges)

#Hough変換による直線の検出
hough_lines = cv2.HoughLinesP(image_edges, 2, np.pi/180, 200, np.array([]), minLineLength= 10, maxLineGap=50)

image_lanelines = show_lines(image, hough_lines)

img_show(image_lanelines,'Hough lines')
cv2.imwrite('image_lanelines.png', image_lanelines)

2022年3月13日日曜日

PiCar-Xでlane detection(01) はじまり

 以前にPiCar-Xでライントレースを行いました。これはMindstormsでも行った白線と黒線の境界をセンサーで検知し、ステアリングを左右するものでした。

その後MindstormsではAfrel(株)の教材に則ってDeep Learningを使ってライントレースを行いましたが、PiCar-XでもまずはPiCameraを使ってのlane detectionから行ってみます。
これは、太い白線の道路中央の黄色いラインをPiCameraで捉えてその黄色いラインの位置情報をもとにステアリングを左右に動かすというものです。(下の動画を参照)

下記の記事を参考にしました。

DeepPiCar — Part 1: How to Build a Deep Learning, Self Driving Robotic Car on a Shoestring Budget

また、Packtより
『Applied Deep Learning and Computer Vision for Self-Driving Cars』
が出版されています。ebookで$32ほどですがPacktでは年に何回かセールを行っており、私は$5で買いました。

まずは現状の様子から


下記に画像処理の大まかな流れを示します。

1.PiCameraから画像の取り込み

2.オリジナル画像から作業領域をクロップ

3.画像をBGRからHSVへ変換

4.OpenCV – inRangeで画像を2値化

5.OpenCV – cannyによるエッジ検出

6.region of interest(注目する領域)を設定

7.OpenCV – HoughLinesPによる直線の検出


プログラム全体のコードはここから

言い訳がましく断わっておきますが、私はプログラムの素人です。無駄なこと、間違っていることが有るかもしれませんが、取りあえず動いたのでお許しください。^^;


 

import time
def make_coordinates(image, line_parameters):
          slope, intercept = line_parameters
          y1 = image.shape[0]
          y2 = int(0)
          x1 = int((y1- intercept)/slope)
          x2 = int((y2 - intercept)/slope)
          return np.array([x1, y1, x2, y2])
        
def line_select(image, lines):
          data = []

          left_parameter = []
          right_parameter = []

          #-------temp----------
          x1, y1, x2, y2 =0, 0, 0, 0
          xt1, yt1, xt2, yt2 =0, 0, 0, 0
          #-------temp----------

          for line in lines:
              xt1, yt1, xt2, yt2 = line.reshape(4)
                            
              #垂直線への対応
              if xt1 == xt2:
                  xt2 = xt2 + 2

              if yt1 > yt2:
                  x1,y1,x2,y2 =  xt2, yt2, xt1, yt1
              else:
                  x1,y1,x2,y2 =  xt1, yt1, xt2, yt2
              
              #イレギュラーな不要な線を検出しないように直線の下端が30pixに満たない直線は除く ➡ この操作が必要かは再度検討
              if y2 > 30:
                  data.append([x1,y1,x2,y2])

          line_data = np.array(data)

          #col_numで指定した列を基準にソートする為のindexを取得
          col_num = 2
          sort_index = np.argsort(line_data[:, col_num])

          #sort_indexを元にline_dataをソート
          sorted_line_data = line_data[sort_index,:]

          #left_line
          x1, y1, x2, y2 = sorted_line_data[0]
          left_parameter = np.polyfit((x1, x2), (y1, y2), 1)

          #right_line
          x1, y1, x2, y2 = sorted_line_data[-1]
          right_parameter = np.polyfit((x1, x2), (y1, y2), 1)
         
          left_line_coordinates = make_coordinates(image, left_parameter)
          right_line_coordinates = make_coordinates(image, right_parameter)
 
          return np.array([left_line_coordinates, right_line_coordinates])
        
def show_lines(image, lines):
          lanelines_image = np.zeros_like(image)
          if lines is not None:
            for line in lines:
              X1, Y1, X2, Y2 = line.reshape(4)
              cv2.line(lanelines_image, (X1, Y1), (X2, Y2), (0,250,0), 10)
          return lanelines_image

def show_lines_result(image, lines):
          lanelines_image = np.zeros_like(image)
          if lines is not None:
            for line in lines:
              X1, Y1, X2, Y2 = line.reshape(4)
              cv2.line(lanelines_image, (X1, Y1), (X2, Y2), (0,0,255), 2)
          return lanelines_image

def reg_of_interest(image):
          Image_height = image.shape[0]
          Image_width = image.shape[1]
#          polygons = np.array([[(0, Image_height*(1/2)),(0, Image_height), (Image_width,Image_height), (Image_width, Image_height*(1/2))]])
          polygons = np.array([[(100, 0),(0, Image_height), (Image_width-40,Image_height), (Image_width-100, 0)]])
          image_mask = np.zeros_like(image)
          cv2.fillPoly(image_mask, np.int32([polygons]), 255)
          masking_image = cv2.bitwise_and(image,image_mask)
          return masking_image

# ---------------------------------------

import cv2
import numpy as np
import os
from imutils.video import VideoStream
from imutils import resize
import time
from datetime import datetime

import sys
sys.path.append(r'/home/pi/picar-x/lib')
from utils import reset_mcu
reset_mcu()
from picarx import Picarx

px = Picarx()
px_power = 1

#
px.set_camera_servo1_angle(-5)

# px.set_camera_servo2_angle(-20)
servo2 = -25

# 写真の保存場所
CAM_DIR = "/home/pi/picar-x/Picamera/Result/"

vs = VideoStream(src=0).start()

while True:
    # ファイルの取込     
    img = vs.read()
    image = resize(img, width=640)
        
    # 画像の高さ 幅を取得
    Image_height, Image_width, c = image.shape
        
    try:
        # オリジナル画像から作業領域をクロップ
        cropped_image = image[int(Image_height/2):int(Image_height/2+100), 0:int(Image_width)]

        # HSV color space
        hsv_image = cv2.cvtColor(cropped_image, cv2.COLOR_BGR2HSV)
        
        # binary conversion 
        lower = np.array([20, 0, 0])
        upper = np.array([40, 255, 255])
        
        masked_image = cv2.inRange(hsv_image, lower, upper)
        
        # Canny edge detection
        canny_conversion = cv2.Canny(masked_image, 50,155)
        
        # region of interest
        ROI_image = reg_of_interest(canny_conversion)
        
        # Hough変換による直線の検出
        Hough_lines = cv2.HoughLinesP(ROI_image, 2, np.pi/180, 50, np.array([]), minLineLength= 20, maxLineGap=20)
        
        # Hough_linesをcropped_imageと同じ大きさの黒色のキャンパスに描画
        lanelines_image = show_lines(cropped_image, Hough_lines)
        
        # left_lineとright_lineの選択
        left_right_lines = line_select(lanelines_image, Hough_lines)
        
        # left-right_linesをcropped_imageと同じ大きさの黒色のキャンパスに描画
        line_image = show_lines_result(cropped_image, left_right_lines)

        # 上のline_imageとcropped_imageとを合成
        combine_image = cv2.addWeighted(cropped_image, 0.8, line_image, 1, 1)


#-------------------------------------------------------------------------        
        #left_line_top
        left_line_top = left_right_lines[0,2]

        #right_line_top
        right_line_top = left_right_lines[1,2]
        
        center_line = (left_line_top + right_line_top)/2

        #image_center
        image_center = Image_width/2
        

#-----------------------------------------------------------------------------        
        # steer
        steer = (center_line - image_center)/image_center * 80
        
        px.set_camera_servo2_angle(servo2)
        px.set_dir_servo_angle(steer)
        px.forward(px_power)
        time.sleep(0.1)
        px.forward(0)
        
        #
        text = 'left:' + str(left_line_top) + ' ' + 'right:' + str(right_line_top)
        
        cv2.putText(combine_image,
            text=text,
            org=(10, 30),
            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
            fontScale=0.7,
            color=(0, 255, 0),
            thickness=1,
            lineType=cv2.LINE_4)
        
        filename = time.strftime("%Y%m%d%H%M%S") + ".jpg"
        save_dir_filename = CAM_DIR + filename
        cv2.imwrite(save_dir_filename,combine_image)

    except:
        #print('Exception!')
        #print('photo No', filename)
        pass



2022年1月8日土曜日

SunFounderのPiCar-X買っちゃいました

 先日Freenoveの4WD Smart Carを買ったばかりですが、また買っちゃいました。ダメなおじんです。




早速、定番の(?)ライントレースをやってみました。gray-scaleセンサーのcenterだけを使って、白色と青色の境界線を識別する一番簡単なものです。on-off制御のみでP制御も入れていません。

なぜ白線と黒地の間に青色があるのか?。それは秘密です。