OpenCV 활용한 Computer Vision - Edge Detection

CROSSORBIT·2022년 7월 4일
0

Image-Processing

목록 보기
4/7
post-thumbnail

개요

에지(edge)는 영상에서 픽셀의 밝기가 급격하게 변하는 부분을 일반적으로 배경과 객체 간, 또는 객체와 객체 간 경계를 의미하며, 에지 검출을 통해 이미지에서 원하는 영역만 찾아낼 수 있습니다.

에지 검출 시 픽셀값 간의 변화율을 계산하는데, 변화율이 큰 픽셀을 에지로 판단합니다. 수학에서의 미분(derivative)을 활용합니다.

주요 기능

1. Sobel

이미지에는 노이즈처럼 보이는 패턴이 있는데, 이 부분이 검출되어 제거되면 에지가 무뎌질 수 있습니다. 이런 영향을 줄이기 위해서는 보다 큰 사이즈의 마스크 이용하여 계산해야 하는데요. 그중 가장 많이 사용되는 것이 소벨 필터 마스크(sobel filter) 입니다. 소벨 필터의 경우 3x3 필터를 활용합니다.

cv2.Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None)
- src: 입력 영상
- ddepth: 출력 영상 데이터 타입. -1이면 입력 영상과 같은 데이터 타입을 사용.
- dx: x 방향 미분 차수.
- dy: y 방향 미분 차수.
- dst: 출력 영상(행렬)
- ksize: 커널 크기. 기본값은 3.
- scale 연산 결과에 추가적으로 곱할 값. 기본값은 1.
- delta: 연산 결과에 추가적으로 더할 값. 기본값은 0.
- borderType: 가장자리 픽셀 확장 방식. 기본값은 cv2.BORDER_DEFAULT.

2.Canny

Canny Edge Detection은 1986년 J.Canny가 제시한 방식으로, 임계값에 대한 민감도, 에지 픽셀의 표현 방식과 같은 소벨 에지 검출의 단점을 보완하기 위해 나온 개념 입니다. 크게 4단계로 수행되는 데요.

  1. 블러링
    - 가우시안 필터링 이용하여 미분 시 발생되는 노이즈 제거

  2. 그래디언트(Gradient) 계산
    - 경사값(미분)을 이용하여 에지 찾기, 주로 소벨 마스크 이용

  3. 비최대 억제(Non-maximum suppression)
    - 하나의 에지가 여러개 픽셀에 표현될 경우 최대 픽셀만 에지로 선정
    - 진짜 에지가 아닌 데 검출된 부분 지우기

  4. 이중 임계값을 이용한 히스테리시스 에지 트래킹
    - Low, High 두개의 임계값으로 구분하여 강한 에지를 최종 에지로 선정.
    - 단, 약한 에지 중 강한 에지와 연결되어 있으면 최종 에지로 포함

threshold 는 에지 여부를 판단하는 기준 임계값을 의미하는데, 임계값이 높으면 밝기 차이가 큰 에지만 검출하고, 낮으면 밝기 차이가 크지 않은 에지를 검출합니다.

cv2.Canny(src, threshold1, threshold2, edges, apertureSize, L2gradient)
- src : 입력 영상
- threshold1 : 하단 임계값
- threshold2 : 상단 임계값 (threshold1 : threshold2 = 1:2 또는 1:3)
- egdes : 에지 영상
- apertureSize 소벨 연산 위한 커널 크기. 기본값은 3
- L2gradient : True 이면 L2 norm, False 이면 L1 norm 사용. 기본값은 False.

image = cv2.imread('./images/shin2.jpg', cv2.IMREAD_COLOR)


gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

sobel_image = cv2.Sobel(gray_image, cv2.CV_8U, 1, 0, 3)
canny_image = cv2.Canny(gray_image, 50, 150)

image_list_title = ['original', 'sobel', 'canny']
image_list = [image, sobel_image, canny_image]
plt_imshow(image_list_title, image_list, figsize=(10, 6))

3. Hough transform

허프 변환 직선 검출은 2차원 영상 좌표에서 직선 방정식을 파라미터 공간으로 변환하여 직선을 찾는 알고리즘입니다.

크게 허프 변환에 의한 선분 검출(cv2.HoughLines)과 확률적 허프 변환에 의한 선분 검출(cv2.HoughLinesP) 2가지 방법이 있는데, 전자는 모든 픽셀에 대해 계산하는데 반해 후자는 픽셀을 확률적(랜덤)으로 선택하여 검사하는 방식입니다.

cv2.HoughLinesP(image, rho, theta, threshold, lines=None,
minLineLength=None, maxLineGap=None) -> lines
- image: 입력 에지 영상
- rho: 축적 배열에서 rho 값의 간격. (e.g.) 1.0 : 1픽셀 간격.
- theta: 축적 배열에서 theta 값의 간격. (e.g.) np.pi / 180 : 1° 간격.
- threshold: 축적 배열에서 직선으로 판단할 임계값
- lines: 선분의 시작과 끝 좌표(x1, y1, x2, y2) 정보를 담고 있는 numpy.ndarray.
- minLineLength: 검출할 선분의 최소 길이
- maxLineGap: 직선으로 간주할 최대 에지 점 간격

canny_image = cv2.Canny(gray_image, 10, 100, apertureSize=3, L2gradient=True)

lines = cv2.HoughLinesP(canny_image, 1, np.pi/180, 160, minLineLength=50, maxLineGap=5)

hough_image = cv2.cvtColor(canny_image, cv2.COLOR_GRAY2BGR)

if lines is not None:
    for i in range(lines.shape[0]):
        pt1 = (lines[i][0][0], lines[i][0][1]) #시작점 좌표
        pt2 = (lines[i][0][2], lines[i][0][3]) #끝점 좌표
        cv2.line(hough_image, pt1, pt2, (0, 0, 255), 2, cv2.LINE_AA)

plt.figure(figsize=(8, 5))
plt.imshow(hough_image)
plt.title('hough_image')
plt.xticks([]), plt.yticks([])

profile
기억과 기록 그 사이 어딘가에서

0개의 댓글