팀 프로젝트/자율주행 개발(baqu4)

[Python] OpenCV로 자율주행 만들기(Canny threshold)

MIRIP 2022. 8. 13. 00:00
반응형

이번에는 threshold방식을 이용하여 인식하고자 하는 물체의 윤곽선을 얻었다.

  • 목표 : 콘 인식 및 주행
  • 개발환경 : IDLE
  • 언어 : python
  • 방식 : 단순 알고리즘(Canny threshold)

위와 같이 계획을 세웠다.


Canny threshold를 이용하면 물체의 윤곽선을 얻을 수 있다.

윤곽선을 보다 정확하게 얻기 위해 Gaussian Filter을 사용하여 이미지의 노이즈를 줄여주었다.

그리고 라바콘이 주황색이라는 점을 고려하여 HSL필터로 나머지 차선과 배경과 같은 노이즈를 없애 주었다.

그 후 Canny threshold 알고리즘을 사용하여 윤곽선을 추출했다. Canny threshold에 대해 더 알고싶으면 아래 사이트를 참조하기 바란다.

 

OpenCV: Canny Edge Detector

Prev Tutorial: Laplace Operator Next Tutorial: Hough Line Transform Goal In this tutorial you will learn how to: Use the OpenCV function cv::Canny to implement the Canny Edge Detector. Theory The Canny Edge detector [40] was developed by John F. Canny in 1

docs.opencv.org

import matplotlib.pyplot as plt
import numpy as np
import cv2

path = "./source/2022-07-04_16-10-12.mp4"
obj = cv2.imread('./source/lavacorn.png', cv2.IMREAD_GRAYSCALE)#wad
cap=cv2.VideoCapture(path)
obj_contours,_=cv2.findContours(obj, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)#wad
obj_pts=obj_contours[0]#wad

fps = cap.get(cv2.CAP_PROP_FPS)
width  = cap.get(cv2.CAP_PROP_FRAME_WIDTH)   # float
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
codec = cv2.VideoWriter_fourcc(*'DIVX')
out=cv2.VideoWriter('output.mp4', codec, 30.0, (int(width),int(height)), isColor=False)

kernel_size=5

low_threshold=200
high_threshold=255

rho=2
theta=np.pi/180
threshold=90
min_line_len=10
max_line_gap=50

a=0.8
b=1.
theta_w=0.

def grayscale(img):
    hsl=cv2.cvtColor(img, cv2.COLOR_BGR2HLS)
    imgH,imgS,imgL=cv2.split(hsl)
    return imgL
    
def gaussian_blur(img, kernel_size):
    return cv2.GaussianBlur(img, (kernel_size, kernel_size), 0)

def canny(img, low_threshold, high_threshold):
    """Applies the Canny transform"""
    return cv2.Canny(img, low_threshold, high_threshold)

def auto_canny(img, sigma):
    """Applies the Canny transform"""
    v=np.median(img)

    lower=int(max(0,(1.0-sigma)*v))
    upper=int(min(255, (1.0+sigma)*v))
    
    return cv2.Canny(img, lower, upper)

def region_of_interest(img, vertices):
    mask=np.zeros_like(img)

    if len(img.shape)>2:
        channel_count = img.shape[2]
        ignore_mask_color=(255,)*channel_count
    else:
        ignore_mask_color=255

    cv2.fillPoly(mask, vertices, ignore_mask_color)

    masked_image=cv2.bitwise_and(img,mask)
    return masked_image

def draw_lines(img, lines, color=[255,0,0], thickness=5):
    for line in lines:
        for x1, y1, x2, y2 in line:
            cv2.line(img, (x1,y1), (x2,y2), color, thickness)

def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap):
    lines=cv2.HoughLinesP(img, rho, theta, threshold, np.array([]), min_line_len, max_line_gap)
    line_img=np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    draw_lines(line_img, lines)
    return line_img

def weighted_img(img, initial_img, a, b, theta_w):
    return cv2.addWeighted(initial_img, a, img, b, theta_w)


while cap.isOpened(): # cap 정상동작 확인
    ret, img = cap.read()
    # 프레임이 올바르게 읽히면 ret은 True
    if not ret:
        print("프레임을 수신할 수 없습니다. 종료 중 ...")
        break

    img = cv2.resize(img, dsize=(640, 360))
    gray=grayscale(img)
    blur_gray=gaussian_blur(gray, kernel_size)

    edges=canny(blur_gray, low_threshold, high_threshold)
    mask=np.zeros_like(img)

    if len(img.shape)>2:
        channel_count=img.shape[2]
        ignore_mask_color=(255,) * channel_count
    else:
        ignore_mask_color=255
    imshape=img.shape

    vertices=np.array([[(0,275),
                       (250, 170),
                       (310, 170),
                       (imshape[1], 275)]], dtype=np.int32) #(0,275)(250, 185)(310, 185)(imshape[1], 275)
    cv2.fillPoly(mask, vertices, ignore_mask_color)
    masked_image=region_of_interest(edges, vertices)

    bigimg=cv2.resize(masked_image, dsize=(1280, 720))

##    작업공간    ##
    contours,_=cv2.findContours(bigimg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for pts in contours:
        if cv2.contourArea(pts) <100:
            continue
        rc=cv2.boundingRect(pts)
        #cv2.rectangle(bigimg, rc, (255, 0,0),1)

        dist=cv2.matchShapes(obj_pts, pts, cv2.CONTOURS_MATCH_I3, 0)
        if dist <0.4:
            cv2.rectangle(bigimg, rc, (255, 0,0),1)

    cv2.imshow('frame1', bigimg)
    out.write(bigimg)
    
    if cv2.waitKey(1) == ord('q'):
        break
# 작업 완료 후 해제
cap.release()
out.release()
cv2.destroyAllWindows()
 

Python에서 OpenCV로 Canny Detection을 이용하는 차선 인식

세상에는 고수가 많고, 그 많은 고수들중 또 많은 분들이 친절(^^)합니다. 요즘은 그 많은 친절한 고수분들의 설명을 따라하는 것 만으로도 참~ 즐거운 공부가 됩니다. 오늘은.. (제가 맨날하는)

pinkwink.kr

위 사이트를 기반으로 코드를 작성하였다. 이전 포스트와 다른 점이 있다면 HSL필터를 사용하여 차선을 인식하던 문제점을 해결하고 콘을 인식하도록 하였다.


output3.mp4
2.30MB

위 동영상에서 보이듯 차선은 전부 제외하고 콘만 인식하도록 만든 것을 볼 수 있다. 하지만 인식률이 떨어지는 문제점이 있었다. 차선이 인식되는 근본적인 문제를 해결하였다는 점에서 본 포스팅은 의의가 크다. 다음 포스팅에서는 콘에 대한 인식률을 높이고 차선을 연결하는 것을 목표로 삼고 진행할 것이다.

 

이전 포스팅이 궁금하다면 아래 사이트를 참조하길 바란다.

 

[Python] Hough transform을 이용하여

 이번 시도에서는 원근법을 사용하여 이미지를 변형하는 방식 대신 차선 그 자체를 인식하는 방법을 사용하였다. 목표 : 콘 인식 및 주행 개발환경 : IDLE 언어 : python 방식 : 단순 알고리즘(허프

codezaram.tistory.com

 

728x90
반응형