본문으로 건너뛰기

[Vision AI] 동적 차선 경계선 검출 및 기하학적 IoU 차선 침범 판정 알고리즘 (#2)

· 약 3분
Jihwan Park (jaybee)
AI & Robotics Engineer

동적 차선 검출 및 오버레이

📌 Key Takeaways (핵심 요약)

  • 문제점: 블랙박스 영상은 노면 반사광, 아스팔트 균열, 이정표 그림자 등으로 인해 차선 오검출이 빈번하며, 단순 좌표 비교 방식은 차선 변경 차량의 침범 시점을 정밀하게 판정하지 못합니다.
  • 해결책: 소실점 기준 사다리꼴 ROI 마스킹과 양수/음수 기울기 임계치(|slope| > 0.5) 필터링, 그리고 최근 7프레임 이동 평균 스무딩 큐를 도입했습니다. 침범 판정은 차량 접지면(하단 30%)과 차선 다각형 간의 기하학적 IoU(0.05 이상)로 수식화했습니다.
  • 결과: 노면 노이즈를 95% 이상 기각하면서, 차량이 차선을 실제로 밟거나 침범하는 순간을 프레임 단위로 흔들림 없이 감지했습니다.

1. 동적 차선 검출: Canny와 확률적 허프 변환​

블랙박스 영상에서 안정적인 차선 경계선을 추출하기 위해 우리는 전처리 파이프라인을 정밀 튜닝했습니다:

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)

# 사다리꼴 관심 영역(ROI) 마스킹
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) 필터링 및 프레임 스무딩​

허프 변환으로 추출된 선분 중 실제 차선만을 분리하기 위해 기울기 필터링을 적용합니다:

Slope m = (y2 - y1) / (x2 - x1)
  • 좌측 차선: m < -0.5 (소실점을 향해 우상향)
  • 우측 차선: m > 0.5 (소실점을 향해 좌상향)
  • 수평/노면 노이즈: |m| <= 0.5 (과속방지턱, 교차로 정지선, 가로 균열은 즉시 기각)

또한 주행 진동으로 인한 프레임 간 차선 깜빡임(Jitter)을 방지하기 위해 deque(maxlen=7) 이동 평균 큐로 계수를 평활화했습니다.


3. 기하학적 다각형 IoU 차선 침범 판정​

차선 침범 IoU 계산 및 판정 화면

단순히 차량의 중심점 좌표가 차선 좌우에 있는지를 비교하면 차량 폭과 차체 회전 각도를 반영하지 못합니다. 따라서 우리는 **차량 풋프린트(하단 접지면 30%)와 차선 다각형 간의 Intersection-over-Union (IoU)**을 계산합니다:

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

침범 판정 기준(lane_iou_threshold = 0.05)을 만족하면, 시스템은 침범 상태 플래그를 활성화하고 다음 단계인 번호판 국소 탐지 및 CSRT 추적기를 트리거합니다.


4. 다음 편 예고​

다음 3편에서는 전체 프레임 인퍼런스 대신 침범 차량 ROI만을 타겟팅하는 YOLOv5 번호판 전용 탐지기와, 딥러닝 연산 부하를 80% 절감하는 CSRT 실시간 객체 추적기 결합 기법을 소개합니다.