สร้างรถขับเองได้! สอนทำ Road Lane Detection ด้วย Raspberry Pi 3 + OpenCV 🚗🛣️

Road Lane Detection with Raspberry Pi

สวัสดีชาว Maker สายซิ่งทุกคนครับ! ในยุคที่เทรนด์รถยนต์ไร้คนขับ (Self-driving cars) กำลังมาแรง ระบบควบคุมและวิศวกรรมต่างๆ ถูกพัฒนาไปไกลมาก แต่รู้ไหมครับว่าพื้นฐานสำคัญอย่างหนึ่งของการนำทางรถยนต์ก็คือ "การตรวจจับเส้นเลนถนน (Road Lane Detection)" นั่นเอง

วันนี้เราจะพามาทำระบบตรวจจับเลนถนนแบบง่ายๆ และประมวลผลไวปรี๊ดด้วย Raspberry Pi 3 คู่กับ OpenCV (ไลบรารีประมวลผลภาพยอดฮิต) โดยโปรเจกต์นี้ตั้งใจหลีกเลี่ยงวิธี Linear regression เพื่อลดภาระการคำนวณ ทำให้เราได้เฟรมเรตสูงถึง 17 FPS เลยทีเดียว! เหมาะมากสำหรับสภาพแวดล้อมที่สัญญาณรบกวนต่ำ (Low noise environment) พร้อมแล้วมาลุยกันเลยครับ!

เตรียมอุปกรณ์ (Hardware Components)

ของที่ต้องใช้มีไม่เยอะครับ เน้นฮาร์ดแวร์พื้นฐานที่สาย DIY น่าจะมีติดบ้านกันอยู่แล้ว:

  • บอร์ดหลัก: Raspberry Pi 3 Model B
  • กล้อง: Raspberry Pi Camera Module
  • ไมโครคอนโทรลเลอร์ช่วยคุมพวงมาลัย: Arduino UNO (สำหรับควบคุม Servo)
  • มอเตอร์: Servos (Tower Pro MG996R) สำหรับกลไกเลี้ยวแบบ Ackermann steering mechanism

💡 Maker's Tip: การทำหุ่นยนต์รถขับเคลื่อนอัตโนมัติ นอกจากวงจรจะเป๊ะแล้ว "แชสซีรถและจุดยึดกล้อง" ก็สำคัญมากครับ แนะนำให้ใช้ เครื่องปริ้นท์ 3D ออกแบบโครงรถและ Mount ยึดกล้อง Pi Camera ให้ได้องศาที่พอดี

หากเพื่อนๆ กำลังมองหา บอร์ด Raspberry Pi, Arduino UNO, มอเตอร์ Servo หรืออยากได้ เส้นพลาสติก 3D Print (Filament) คุณภาพสูงเพื่อไปปริ้นท์โครงรถสุดเท่ แวะมาเลือกช้อปของแท้พร้อมส่งได้ที่ Globalbyte เลยครับ! มีของแต่งโปรเจกต์เพียบ!

การตั้งค่าฮาร์ดแวร์และกล้อง (Camera Configuration)

เริ่มต้นจากการต่อสายแพของ Pi Camera เข้ากับพอร์ต CSI บนบอร์ด Raspberry Pi ให้เรียบร้อยครับ (หันแถบสีน้ำเงินหรือจุดคอนแทคให้ถูกฝั่ง)

Connecting Pi Camera
การเชื่อมต่อสายกล้องเข้ากับพอร์ตบนบอร์ด Raspberry Pi

สำหรับการตั้งค่ากล้องบนระบบปฏิบัติการ (Enable Camera) สามารถทำตามคู่มือทางการของ Raspberry Pi ได้ที่ ลิงก์นี้เลยครับ

การติดตั้งซอฟต์แวร์ OpenCV (Software Setup)

เราต้องลงไลบรารี OpenCV สำหรับ Python ซึ่งขั้นตอนนี้จะใช้เวลา Compile นานพอสมควร (ประมาณ 2 ชั่วโมง) ดังนั้นเสียบสายชาร์จและตั้งจอทิ้งไว้ได้เลยครับ ให้เปิด Terminal แล้วรันคำสั่งพื้นฐาน (Generic stuff) เหล่านี้ก่อน:

Terminal (Generic Dependencies)
sudo apt-get update
sudo apt-get upgrade
sudo rpi-update
sudo reboot
sudo apt-get install build-essential git cmake pkg-config
sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt-get install libxvidcore-dev libx264-dev
sudo apt-get install libgtk2.0-dev
sudo apt-get install libatlas-base-dev gfortran
cd ~
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout 3.1.0
cd ~
git clone https://github.com/opencv/opencv_contrib.git
cd opencv_contrib
git checkout 3.1.0

จากนั้นให้เลือกรันคำสั่งติดตั้งตามเวอร์ชัน Python ที่คุณใช้งานครับ (เลือกอันใดอันหนึ่ง)

Terminal (For Python 2.7)
sudo apt-get install python2.7-dev
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
pip install numpy
cd ~/opencv
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D INSTALL_C_EXAMPLES=OFF \
    -D INSTALL_PYTHON_EXAMPLES=ON \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
    -D BUILD_EXAMPLES=ON ..
make -j4
sudo make install
sudo ldconfig
Terminal (For Python 3)
sudo apt-get install python3-dev
wget https://bootstrap.pypa.io/get-pip.py
sudo python3 get-pip.py
pip install numpy
cd ~/opencv
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D INSTALL_C_EXAMPLES=OFF \
    -D INSTALL_PYTHON_EXAMPLES=ON \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
    -D BUILD_EXAMPLES=ON ..
make -j4
sudo make install
sudo ldconfig

ทฤษฎีเบื้องหลัง: Hough Transform คืออะไร?

ระหว่างที่รอ Raspberry Pi รันคำสั่ง Make (ประมาณ 2 ชั่วโมง) เรามาทำความเข้าใจ Hough Transform กันก่อนครับ เทคนิคนี้คือหัวใจสำคัญที่อยู่เบื้องหลังอัลกอริทึมการตรวจจับเส้นเลนในโลกความจริงส่วนใหญ่เลยล่ะ ลองดูวิดีโออธิบายการทำงานจากคุณ Thales Sehn Körting ด้านล่างนี้ได้เลยครับ (สามารถอ่าน Documentation ของ opencv-python เพิ่มเติมได้ที่นี่)

โค้ด Python สำหรับ Raspberry Pi (Lane Detection)

เมื่อลง OpenCV เสร็จแล้ว ให้รันโค้ด Python ด้านล่างนี้ครับ โค้ดนี้จะใช้ cv2.HoughLinesP เพื่อหาเส้นขอบถนน และคำนวณมุม (Theta) หากมุมเกินค่า Threshold (ค่าความคลาดเคลื่อน) ที่ตั้งไว้ ระบบจะสั่งงานผ่านขา GPIO ของ Pi เพื่อส่งสัญญาณให้ Arduino หักพวงมาลัยเลี้ยวซ้ายหรือขวาครับ

Python (Raspberry Pi Camera & OpenCV)
from picamera.array import PiRGBArray
import RPi.GPIO as GPIO
from picamera import PiCamera
import time
import cv2
import numpy as np
import math

GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
GPIO.setup(8, GPIO.OUT)
theta=0
minLineLength = 5
maxLineGap = 10
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 30
rawCapture = PiRGBArray(camera, size=(640, 480))
time.sleep(0.1)

for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
   image = frame.array
   gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
   blurred = cv2.GaussianBlur(gray, (5, 5), 0)
   edged = cv2.Canny(blurred, 85, 85)
   lines = cv2.HoughLinesP(edged,1,np.pi/180,10,minLineLength,maxLineGap)
   
   if(lines !=None):
       for x in range(0, len(lines)):
           for x1,y1,x2,y2 in lines[x]:
               cv2.line(image,(x1,y1),(x2,y2),(0,255,0),2)
               theta=theta+math.atan2((y2-y1),(x2-x1))
   
   #print(theta)
   # GPIO pins were connected to arduino for servo steering control
   threshold=6
   if(theta>threshold):
       GPIO.output(7,True)
       GPIO.output(8,False)
       print("left")
   if(theta<-threshold):
       GPIO.output(8,True)
       GPIO.output(7,False)
       print("right")
   if(abs(theta)<threshold):
      GPIO.output(8,False)
      GPIO.output(7,False)
      print("straight")
      
   theta=0
   cv2.imshow("Frame",image)
   key = cv2.waitKey(1) & 0xFF
   rawCapture.truncate(0)
   if key == ord("q"):
       break

ตัวอย่างผลลัพธ์การทำงาน (Sample Outputs)

มาดูภาพตัวอย่างการใช้ Hough Transform ตรวจจับขอบของเส้นเลน (สีเขียว) กันครับ!

Lane Detection Output 1 Lane Detection Output 2 Lane Detection Output 3 Steering Mechanism Output

โค้ด Arduino สำหรับคุมพวงมาลัย (Servo Control)

ในฝั่งของมอเตอร์บังคับเลี้ยว เราจะต่อขา GPIO จาก Raspberry Pi เข้ากับบอร์ด Arduino Mega / UNO เพื่อทำหน้าที่อ่านสัญญาณ (HIGH/LOW) แล้วสั่งให้ Servo Motor หมุนทำมุมเลี้ยวซ้าย (118 องศา), ขวา (62 องศา) หรือตรง (90 องศา) ครับ

C++ (Arduino IDE - Servo Control)
#include <Servo.h>

Servo myservo;

void setup() {
  myservo.attach(10); // attach servo motor PWM (orange) wire to pin 10 
  pinMode(0, INPUT);  // attach GPIO 7 & 8 pins from Pi to arduino pin 0 & 1
  pinMode(1, INPUT);
}

void loop() {
  if(digitalRead(0)==HIGH && digitalRead(1)==LOW)
  {
        myservo.write(118);
  }
  if(digitalRead(1)==HIGH && digitalRead(0)==LOW)
  {
        myservo.write(62);
  }
  if(digitalRead(1)==LOW && digitalRead(0)==LOW)
  {
         myservo.write(90);
  } 
}

นี่เป็นเพียงจุดเริ่มต้นของการทำรถยนต์อัตโนมัติเท่านั้น หากใครมีไอเดียเจ๋งๆ หรืออยากลองปรับปรุงโค้ดให้หลบหลีกสิ่งกีดขวางได้ด้วย ก็ลองนำไปต่อยอดกันดูนะครับ!

อ้างอิงและเรียบเรียงข้อมูลจาก: Globalbyteshop Blog

แหล่งที่มาโปรเจกต์ต้นฉบับ: Hackster.io - Road Lane Detection with Raspberry Pi (by Abhinav_Abhi)

*คำเตือน: เนื้อหานี้เป็นการสรุปและเรียบเรียงแนวคิดจากโปรเจกต์ต้นฉบับภาษาอังกฤษ ข้อมูลการติดตั้งโปรแกรมและโค้ดที่แสดงในบทความอาจต้องมีการปรับแก้ให้ตรงกับเวอร์ชันของ OS และฮาร์ดแวร์ของผู้ใช้งาน ผู้สนใจควรศึกษารายละเอียดเชิงลึก ข้อจำกัดของระบบ และวิธีแก้ปัญหาเพิ่มเติมจาก เว็บไซต์ต้นฉบับ ก่อนลงมือปฏิบัติ

 

แท็ก


Blog posts

เข้าสู่ระบบ

ลืมรหัสผ่านใช่ไหม?

ยังไม่มีบัญชีใช่ไหม?
สร้างบัญชี