Skip to main content

[Vision AI] Dynamic Lane Boundary Extraction & Geometric IoU Intrusion Criterion (#2)

· 2 min read
Jihwan Park (jaybee)
AI & Robotics Engineer

Dynamic Lane Detection Overlay

📌 Key Takeaways (TL;DR)

  • Problem: Dashcam footage contains heavy pavement specular reflection, tar cracks, and road shadows that induce false lane lines; simple coordinate checking cannot reliably catch the exact moment of lane encroachment.
  • Solution: Implemented vanishing-point trapezoidal ROI masking, slope thresholding (|slope| > 0.5), and a 7-frame temporal moving average queue. Formulated intrusion as geometric IoU between vehicle tire footprints and lane boundaries.
  • Result: Filtered out >95% of road texture noise while capturing vehicle lane crossing events with sub-frame accuracy.

1. Dynamic Lane Detection: Canny & Probabilistic Hough Transform​

def detect_lanes(frame):
height, width = frame.shape[:2]
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blur, 50, 150)

mask = np.zeros_like(edges)
roi_polygon = np.array([[
(int(width * 0.1), height),
(int(width * 0.45), int(height * 0.6)),
(int(width * 0.55), int(height * 0.6)),
(int(width * 0.9), height)
]], np.int32)
cv2.fillPoly(mask, roi_polygon, 255)
masked_edges = cv2.bitwise_and(edges, mask)

lines = cv2.HoughLinesP(
masked_edges,
rho=1,
theta=np.pi / 180,
threshold=20,
minLineLength=20,
maxLineGap=10
)
return lines

2. Slope Filtering & Temporal Smoothing​

Raw line segments are filtered using slope criteria:

Slope m = (y2 - y1) / (x2 - x1)
  • Left Lane: m < -0.5
  • Right Lane: m > 0.5
  • Horizontal Noise: |m| <= 0.5 (crosswalks and bumps are rejected)

A deque(maxlen=7) temporal moving average smooths lane equations across consecutive frames.


3. Geometric Polygon IoU Lane Intrusion Criterion​

Lane Intrusion IoU Evaluation

Footprint = [x_min, y_min + 0.7*h, x_max, y_max]
IoU = Area(Footprint ∩ Lane_Polygon) / Area(Footprint)
def check_lane_intrusion(vehicle_box, lane_polygon, threshold=0.05):
vx1, vy1, vx2, vy2 = vehicle_box
vh = vy2 - vy1
footprint = Polygon([(vx1, vy1 + 0.7*vh), (vx2, vy1 + 0.7*vh), (vx2, vy2), (vx1, vy2)])

intersection = footprint.intersection(lane_polygon).area
iou = intersection / footprint.area
return iou > threshold, iou

When IoU > 0.05, the system flags a violation event and triggers YOLOv5 license plate localization.


4. Looking Forward​

In Post #3, we explore hierarchical object detection with fine-tuned YOLOv5 (lp_det.pt) and real-time CSRT tracking integration to slash GPU inference overhead by 80%.