Computer Vision/opencv(python)

[37] 4) 허프 변환: 직선 검출

jwjwvison 2021. 3. 22. 14:32
  • 허프 변환(Hough transform) 직선 검출이란?
    • 2차원 영상 좌표에서의 직선의 방정식을 파라미터(parameter)공간으로 변환하여 직선을 찾는 알고리즘

 

  • 축적 배열(accumulation array)
    • 직선 성분과 관련된 원소 값을 1씩 증가시키는 배열

 

  • 직선의 방정식 y=ax+b를 사용할 때의 문제점
    • y축과 평행한 수직선을 표현하지 못함 -> 극좌표계 직선의 방정식을 사용

 

  • 허브 변환에 읜한 선분 검출
cv2.HoughLines(image,rho,theta,threshold,line=None,srn=None,stn=None,min_theta=None,max_theta=None) -> lines

 • image: 입력 에지 영상
 • rho: 축적배열에서rho 값의간격. (e.g.) 1.0 -> 1픽셀간격.

 • theta: 축적배열에서 theta 값의 간격 (e.g.) np.pi/180 -> 1도 간격

 • threshold: 축적 배열에서 직선으로 판단할 임계값

 • lines: 직선 파라미터 (rho,theta) 정보를 담고 있는 numpy.ndarray. shape=(N,1,2).dtype=numpy.float32

 • srn, stn: 멀티 스케일 허프 변환에서 rho 해상도, theta 해상도를 나누는 값. 기본값은 0이고, 이 경우 일반 허프 변환 수행

 • min_theta, max_theta: 검출할 선분의 최소, 최대 theta 값

 

  • 확률적 허프 변환에 의한 선분 검출
cv2.HoughLinesP(image,rho,theta,threshold,line=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. shape=(N,1,4).dtype=numpy.int32

 • minLineLength: 검출할 선분의 최소 길이

 • maxLineGap: 직선으로 간주할 최대 에지 점 간격

 

  • 확률적 허프 변환 직선 검출 예제
import sys
import numpy as np
import cv2


src = cv2.imread('building.jpg', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

edges=cv2.Canny(src,50,150)
lines=cv2.HoughLinesP(edges,1.0,np.pi/180,160,minLineLength=50,maxLineGap=5)     
#rho 값이 작으면 축적배열이 커지고 rho 값이 크면 축적배열이 작아진다. 
# 축적배열이 작아지면 시간은 빠르지만 정밀하지가 않다
#360도로 나누면 정교해지만 느리다
#threshold는 축적배열에서 몇 이상부터 직선으로 판단할지 임계값이다. threshold가 낮으면 많은 직선이 검출될수 있다.
#lines은 선분의 시작과 끝 좌표(x1,y1,x2,y2) shape=(N,1,4) 중간값은 무시
dst=cv2.cvtColor(edges,cv2.COLOR_GRAY2BGR)

if lines is not None:
    for i in range(lines.shape[0]):    #range(N)
        pt1=(lines[i][0][0],lines[i][0][1])
        pt2=(lines[i][0][2],lines[i][0][3])
        cv2.line(dst,pt1,pt2,(0,0,255),2,cv2.LINE_AA)


cv2.imshow('edges',edges)
print(lines)
cv2.imshow('dst',dst)
cv2.waitKey()