이진화를 통한 차선 간단한 차선 인식 방법

Sinaenjuni·2023년 4월 10일

아이디어

이진화된 이미지의 특정 부분을 수평으로 잘라 도로를 의미하는 0(검은색)과 차선을 의미하는 0이 아닌 다른 값을 갖는 영역을 찾는 방법으로 차선을 인식할 수 있다.

데이터 전처리 방법

차선 인식을 위한 데이터 전처리 방법은 다음과 같다.
원본 이미지 -> Gray scale(흑백 이미지) -> Gaussian blur(노이즈 제거) -> HSV binary(색표현) -> ROI(관심영역)

import cv2

img = cv2.imread('img.png')
# 원본 이미지
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 흑백 이미지 변환
blur = cv2.GaussianBlur(gray, (5,5), 0)
# 노이즈 제거
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
lower_white = np.array([0,0,70])
uppper_white = np.array([131,255,255])
mask = cv2.inRange(hsv, lower_white, upper_white)

cv2.imshow('ori', img)
cv2.imshow('gray', gray)
cv2.imshow('blur', blur)
cv2.imshow('gray', mask)

cv2.waitKey(10000)

차선 검출을 위한 파이썬 코드

import cv2
import numpy as np

img = cv2.imread('img.png')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_white = np.array([0,0,70])
uppper_white = np.array([131,255,255])
mask = cv2.inRange(hsv, lower_white, upper_white)

xx = 20
while True:
	area = img[430:450, xx:xx+15]
	if cv2.countNonZero(area) > 200:
    	img = cv2.rectagle(img, (xx,430), (xx+15, 450), (0,255,0), 3)
	else:
    	img = cv2.rectagle(img, (xx,430), (xx+15, 450), (255,0,0), 3)
	xx+=20
    
    if xx > 640:
    	break

cv2.imshow('countNonZero', img)
cv2.waitKey(10000)

Canny edge detector를 이용한 차선 인식

import cv2

img = cv2.imread('img.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5),0)
edge = cv2.Canny(blur, 20, 190)
# 20~190을 기준으로 선을 찾는다.

cv2.imshow('edge', edge)
cv2.waitKey(10000)

패키지 생성

catkin_create_pkg line_drive rospy tf geometry_msgs rviz xacro
#!/usr/bin/env python

import cv2, time
import numpy as np

cap = cv2.VideoCapture('track1.avi')

threshold_60 = 60

width_640 = 640
scan_width_200, scan_height_20 = 200, 20
lmid_200, rmid_440 = scan_width_200, width_640 - scan_width_200
area_width_20, area_height_10 = 20, 10
vertical_430 = 430
row_begin_5 = (scan_height_20 - area_height_10) // 2
row_end_15 = row_begin_5 + area_height_10
pixel_threshold_160 = 0.8 * area_width_20 * area_height_10

while True:
    ret, frame = cap.read()
    if not ret:
        break
    if cv2.waitKey(1) & 0xFF == 27:
        break

    roi = frame[vertical_430:vertical_430 + scan_height_20, :]
    frame = cv2.rectangle(frame, (0, vertical_430),
        (width_640 - 1, vertical_430 + scan_height_20),
        (255, 0, 0), 3)
    hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

    lbound = np.array([0, 0, threshold_60], dtype=np.uint8)
    ubound = np.array([131, 255, 255], dtype=np.uint8)

    bin = cv2.inRange(hsv, lbound, ubound)
    view = cv2.cvtColor(bin, cv2.COLOR_GRAY2BGR)

    left, right = -1, -1

    for l in range(area_width_20, lmid_200):
        area = bin[row_begin_5:row_end_15, l - area_width_20:l] 
        if cv2.countNonZero(area) > pixel_threshold_160:
            left = l
            break

    for r in range(width_640 - area_width_20, rmid_440, -1):
        area = bin[row_begin_5:row_end_15, r:r + area_width_20]
        if cv2.countNonZero(area) > pixel_threshold_160:
            right = r
            break

    if left != -1:
        lsquare = cv2.rectangle(view,
                                (left - area_width_20, row_begin_5),
                                (left, row_end_15),
                                (0, 255, 0), 3)
    else:
        print("Lost left line")

    if right != -1:
        rsquare = cv2.rectangle(view,
                                (right, row_begin_5),
                                (right + area_width_20, row_end_15),
                                (0, 255, 0), 3)
    else:
        print("Lost right line")

    cv2.imshow("origin", frame)
    cv2.imshow("view", view)

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    lbound = np.array([0, 0, threshold_60], dtype=np.uint8)
    ubound = np.array([131, 255, 255], dtype=np.uint8)   
    hsv = cv2.inRange(hsv, lbound, ubound)
    cv2.imshow("hsv", hsv) 

    time.sleep(0.1)

cap.release()
cv2.destroyAllWindows()

0개의 댓글