자율주행/컴퓨터 비젼 프로젝트(python)

OpenCV LaneDetection프로젝트

nosungmin 2023. 2. 11. 18:55
import cv2
import numpy as np
import math
from google.colab.patches import cv2_imshow
file_name = 'car3.jpeg'
frame = cv2.imread(file_name)
cv2_imshow(frame)
height, width, channels = frame.shape
print(height, width, channels)
 
이번 프로젝트에 쓰일 이미지 파일 로드
# Conver the image to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
cv2_imshow(gray)
height, width = gray.shape
 
# GaussianBlur for refucing noise
#위 코드에서는 gray라는 이미지에 대해 (5, 5) 크기의 필터와 표준 편차 0을 사용하여 가우시안 필터를 적용한 결과를 blur 변수에 저장하고 있습니다. 이를 통해 blur 변수에는 gray 이미지에서 노이즈가 제거된 이미지가 저장됩니다.
blur = cv2.GaussianBlur(gray, (55), 0)
cv2_imshow(blur)
 
 
 
연산과 검출을 좀 더 정확하고 쉽게 하기 위해 그레변환과 가우시안 블러를 이용하여 노이즈를 제거한다.
 
#이 코드는 cv2.GaussianBlur 함수를 이용하여 노이즈가 제거된 이미지인 blur에 대해 캐니 엣지 검출을 수행하는 과정입니다.
#cv2.Canny 함수는 입력 이미지를 받아서 캐니 엣지 검출 알고리즘을 적용하여 엣지 픽셀을 검출한 후, 이를 이용하여 엣지를 추출한 이미지를 반환합니다.
# 함수의 첫 번째 인자로는 입력 이미지를, 두 번째 인자로는 최소 엣지 강도를, 세 번째 인자로는 최대 엣지 강도를 전달합니다.
#위 코드에서는 blur 이미지에 대해 최소 엣지 강도를 40, 최대 엣지 강도를 130으로 설정하여 캐니 엣지 검출을 수행한 후, 그 결과를 canny 변수에 저장하고 있습니다. 
#이를 통해 canny 변수에는 blur 이미지에서 추출된 엣지를 검출한 이미지가 저장됩니다. 마지막으로 cv2_imshow 함수를 이용하여 canny 이미지를 출력하고 있습니다.
canny = cv2.Canny(blur, 40130)
cv2_imshow(canny)

mask = np.zeros((height,width), dtype='uint8')
poly_heigh = int(0.60 * height)
poly_left = int(0.47 * width)
poly_right = int(0.53 * width)
polygons = np.array([[(0,height), (poly_left, poly_heigh), (poly_right, poly_heigh), (width, height)]])
cv2.fillPoly(mask, polygons, 255)
cv2_imshow(mask)

이 코드는 Python의 OpenCV 라이브러리를 사용하여 이미지에 마스크를 적용하는 코드입니다.

첫 번째 줄에서는 height와 width 크기의 모든 요소가 0인 2차원 배열인 mask를 만듭니다. 이는 마스크 이미지를 생성하는 초기화 작업을 수행합니다.

두 번째 줄에서는 마스크 이미지의 다각형 영역을 정의하기 위해 poly_height, poly_left, poly_right 변수를 계산합니다. poly_height는 이미지 높이의 60% 위치에 해당하는 값을, poly_left와 poly_right는 이미지 너비의 47%와 53% 위치에 해당하는 값을 계산합니다.

세 번째 줄에서는 polygons 배열을 생성하여 이미지에 적용할 다각형의 꼭짓점 좌표를 지정합니다. 이 경우 다각형의 꼭짓점은 이미지의 왼쪽 하단, 다각형의 왼쪽 상단, 오른쪽 상단, 그리고 오른쪽 하단에 위치합니다.

마지막으로 cv2.fillPoly() 함수를 사용하여 mask 이미지에 다각형을 그리고, 그 안쪽을 흰색으로 채웁니다(255 값). 이렇게 생성된 마스크 이미지를 cv2_imshow() 함수를 사용하여 출력합니다.

결과적으로, 이 코드는 이미지의 하단 중앙에 위치한 직사각형 영역을 제외한 부분을 마스크 처리합니다.

 

 

# Bitwise operation between poly and mask
masked = cv2.bitwise_and(canny, mask)
cv2_imshow(masked)

 
 
 
lines = cv2.HoughLinesP(masked, 2, np.pi / 18020, np.array([]), 2010)

이 코드는 masked 이미지에서 직선을 검출하는 cv2.HoughLinesP 함수를 호출합니다.

cv2.HoughLinesP 함수는 허프 변환(Hough transform) 알고리즘을 이용하여 이미지에서 직선을 검출하는 함수입니다. cv2.HoughLinesP 함수의 첫 번째 인자는 입력 이미지(masked 이미지)를 의미합니다.

두 번째, 세 번째 인자는 각각 거리와 각도의 해상도를 의미합니다. 더 정확하게 말하면, 두 점 사이의 거리(2), 각도(np.pi / 180)의 최소 단위를 설정하는 인자와 같습니다. 이 코드에서는 거리의 최소 단위를 2로, 각도의 최소 단위를 np.pi / 180로 설정하고 있습니다.

네 번째 인자는 허프 변환 알고리즘이 직선으로 판단하는 기준 거리(20)입니다. 다섯 번째 인자는 허프 변환 알고리즘이 판단한 직선의 정보를 저장할 배열을 의미합니다. 여기서는 빈 배열(np.array([]))을 전달하여 자동으로 생성되도록 설정하였습니다.

여섯 번째, 일곱 번째 인자는 각각 검출된 직선의 최소 길이(20)와 최대 간격(10)을 의미합니다. 이를 통해 노이즈나 부적절한 선분을 제거하여 직선 검출의 정확도를 높일 수 있습니다.

cv2.HoughLinesP 함수는 검출된 직선의 시작점과 끝점의 좌표(x1, y1, x2, y2)를 반환합니다. 이 값을 lines 변수에 저장하고, 이후에는 for문과 cv2.line 함수를 이용하여 이미지에 검출된 직선을 그리는 작업 등을 수행할 수 있습니다.

 

image_rgb = cv2.cvtColor(canny, cv2.COLOR_GRAY2RGB)
if lines is not None:
    for line in lines:
        print(line)
        x1, y1, x2, y2 = line.reshape(4)
        cv2.line(image_rgb, (x1, y1), (x2, y2), (00255), 1)
    cv2_imshow(image_rgb)
 

이 코드는 이전 단계에서 추출한 에지(canny) 이미지에서 직선을 검출한 후, 해당 직선들을 시각화하는 작업을 수행합니다.

먼저 cv2.cvtColor 함수를 이용하여 canny 이미지를 회색조에서 RGB 컬러 이미지로 변환합니다. 이후, lines 변수가 None이 아닌 경우에는 for문을 통해 lines 변수에서 각각의 직선 정보를 추출합니다.

각 직선 정보는 네 개의 값(x1, y1, x2, y2)으로 구성되어 있습니다. 이는 각각 직선의 시작점과 끝점의 좌표를 의미합니다. 이 값들을 cv2.line 함수를 이용하여 이미지에 그립니다. 이때, image_rgb 변수를 이용하여 RGB 컬러 이미지에 직선을 그리고 있습니다. cv2.line 함수의 다섯 번째 인자는 직선을 그릴 색상을 의미합니다. 이 코드에서는 빨간색((0, 0, 255))으로 직선을 그리고 있습니다.

마지막으로 cv2_imshow 함수를 이용하여 image_rgb 이미지를 출력합니다. 이는 에지 이미지에서 검출된 직선들이 빨간색으로 그려진 결과 이미지를 의미합니다.

 

for line in lines:
    for x1, y1, x2, y2 in line:
        cv2.line(frame, (x1, y1), (x2, y2), (0255255), 1)
cv2_imshow(frame)
 

이 코드는 이전에 검출된 직선들(lines)을 이용하여 원본 이미지(frame)에 직선을 그리는 코드입니다.

for문을 이용하여 lines에 저장된 직선 정보들을 하나씩 꺼내며, 각각의 직선 정보에 대해 x1, y1, x2, y2 좌표를 추출합니다. 이어서 cv2.line 함수를 호출하여 frame 이미지에 해당 직선을 그리는 작업을 수행합니다.

cv2.line 함수의 첫 번째 인자는 직선을 그릴 대상 이미지(frame)입니다. 두 번째, 세 번째 인자는 각각 시작점과 끝점의 좌표를 의미하는 x1, y1, x2, y2입니다. 네 번째 인자는 직선의 색상((0, 255, 255))입니다. 다섯 번째 인자는 직선의 두께(1)입니다.

이렇게 cv2.line 함수를 호출하여 frame 이미지에 모든 검출된 직선들을 그리면, 최종적으로 원본 이미지에 직선이 표시된 이미지가 출력됩니다.