Lane detection is the foundational computer vision task behind every self-driving car and autonomous robot. Using OpenCV and a Raspberry Pi camera, you can implement a working lane detection self-driving OpenCV Pi system that identifies road lanes in real time and calculates steering commands. This tutorial covers edge detection, Hough transforms, region-of-interest masking, and closed-loop steering control for India robotics projects.
Table of Contents
- How Lane Detection Works
- Hardware Requirements
- Image Preprocessing Pipeline
- Hough Line Transform
- Calculating Steering Angle
- Building a Test Track in India
- FAQ
How Lane Detection Works
The classical pipeline: Grayscale conversion, Gaussian blur, Canny edge detection, Region-of-Interest mask, Hough line transform, lane averaging, and steering angle calculation. This runs at 30+ FPS on Raspberry Pi 4 for straight tracks and is ideal for India robotics lab projects.
Hardware Requirements
Arducam OV2640 Wide-Angle Camera Module
160-degree FOV wide-angle camera perfect for lane detection robots. Captures wide road view with minimal distortion. Compatible with Raspberry Pi CSI port.
Waveshare IMX219-160 Wide Angle Camera
IMX219 sensor with 160-degree FOV, 8MP resolution, ideal for Raspberry Pi 4/5 lane following robots. Excellent low-light performance for indoor tracks.
Image Preprocessing Pipeline
import cv2, numpy as np
from picamera2 import Picamera2
def preprocess(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blur, 50, 150)
h, w = edges.shape
mask = np.zeros_like(edges)
poly = np.array([[(0,h),(w,h),(int(w*0.6),int(h*0.4)),(int(w*0.4),int(h*0.4))]], dtype=np.int32)
cv2.fillPoly(mask, poly, 255)
return cv2.bitwise_and(edges, mask)
Hough Line Transform for Lane Detection
def detect_lanes(frame):
edges = preprocess(frame)
lines = cv2.HoughLinesP(edges, 1, 3.14159/180, 50, minLineLength=40, maxLineGap=100)
left, right = [], []
if lines is None: return None, None
for line in lines:
x1,y1,x2,y2 = line[0]
if x2==x1: continue
s = (y2-y1)/(x2-x1)
b = y1 - s*x1
if s 0.5: right.append((s,b))
h = frame.shape[0]
def coords(s,b):
y1=h; y2=int(h*0.4)
return [int((y1-b)/s),y1,int((y2-b)/s),y2]
L = coords(*np.mean(left,axis=0)) if left else None
R = coords(*np.mean(right,axis=0)) if right else None
return L, R
Calculating Steering Angle
def steer(frame, L, R):
w = frame.shape[1]
cx = w // 2
if L is None and R is None: return 0
if L and R: centre = (L[0]+R[0])//2
elif L: centre = L[0]+320
else: centre = R[0]-320
return int((centre-cx)/cx*45)
# Main loop
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={'size':(640,480),'format':'BGR888'}))
picam2.start()
while True:
frame = picam2.capture_array()
L, R = detect_lanes(frame)
angle = steer(frame, L, R)
print(f'Steering: {angle} degrees', end='r')
# send angle to motor driver here
if cv2.waitKey(1) & 0xFF == ord('q'): break
Pi Camera CSI FPC Ribbon Cable 15cm
Replacement FPC ribbon cable for Raspberry Pi Camera. 15cm length suitable for robot chassis mounting. Essential spare for your lane-following build.
Building a Test Track in India
Use white electrical tape on dark floor – available at any hardware store in India for Rs 30-50 per roll. Track width: 30-40cm between inner lane edges. Avoid direct sunlight which creates strong shadows. If tile grout lines cause false detections, increase minLineLength=80 in HoughLinesP. Total material cost for a 2m x 2m test track: under Rs 200.
FAQ
What camera resolution should I use for lane detection?
640×480 at 30 FPS is the sweet spot on Raspberry Pi 4. Higher resolutions reduce frame rate significantly.
Why does my steering angle jump erratically?
Apply temporal smoothing with a rolling average of the last 5-10 steering angles. Also increase HoughLinesP threshold to filter weak detections.
Can this work outdoors on Indian roads?
Indian road markings are often faded or missing. For outdoor use, apply adaptive thresholding before Canny and use HSV colour filtering for yellow/white lanes.
How do I integrate with motor control?
Send the steering angle via serial to an Arduino motor controller, or directly drive PWM on Pi GPIO pins using RPi.GPIO or pigpio libraries.
Add comment