허프 변환¶
Goal¶
- 허프 변환에 대해서 알수 있다.
- 허프 변환을 이용하여 이미지의 Line을 찾을 수 있다.
- 허프 변환에서 사용하는
cv2.HoughLines(),cv2.HoughLinesP()함수에 대해서 알 수 있다.
Theory¶
허프변환은 이미지에서 모양을 찾는 가장 유명한 방법입니다. 이 방법을 이용하면 이미지의 형태를 찾거나, 누락되거나 깨진 영역을 복원할 수 있습니다.
기본적으로 허프변환의 직선의 방정식을 이용합니다. 하나의 점을 지나는 무수한 직선의 방적식은 y=mx+c로 표현할 수 있으며, 이것을 삼각함수를 이용하여 변형하면 r = 𝑥 cos 𝜃 + 𝑦 sin 𝜃 으로 표현할 수 있습니다.
그럼 아래 이미지를 보고 설명을 하겠습니다. 3개의 점이 있고, 그중 우리가 찾는 직선은 핑크색 직선 입니다.
그럼 각 점(x,y)에 대해서 삼각함수를 이용하여 𝜃 값을 1 ~ 180까지 변화를 하면서 원점에서 (x,y)까지의 거리(r)을 구합니다. 그러면 (𝜃, r)로 구성된 180개의 2차원 배열을 구할 수 있습니다.
동일한 방법으로 두번째 점에 대해서도 𝜃값을 변화해 가면서 2차원 배열을 구합니다.
(출처: 위키 피디아 )
이렇게 해서 구해서 2차원 배열을 다시 그래프로 표현하면 아래와 같이 사인파 그래프로 표현이 됩니다. 아래 3개의 방정식의 만나는 점이 바로 직선인 확율이 높은 점 입니다. 즉, 𝜃가 60이고 거리가 80인 직선의 방정식을 구할 수 있는 것 입니다.
OpenCV를 이용한 허프변환¶
OpenCV는 위에서 설명한 수학적 이론이 cv2.HoughLines() 함수에 구현이 되어 있습니다.
-
cv2.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]]) → lines Parameters: - image – 8bit, single-channel binary image, canny edge를 선 적용.
- rho – r 값의 범위 (0 ~ 1 실수)
- theta – 𝜃 값의 범위(0 ~ 180 정수)
- threshold – 만나는 점의 기준, 숫자가 작으면 많은 선이 검출되지만 정확도가 떨어지고, 숫자가 크면 정확도가 올라감.
Sample Code
#-*- coding:utf-8-*-
import cv2
import numpy as np
img = cv2.imread(r'images\chessboard\frame01.jpg')
img_original = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize=3)
lines = cv2.HoughLines(edges,1,np.pi/180,100)
for i in xrange(len(lines)):
for rho, theta in lines[i]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0+1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 -1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
res = np.vstack((img_original,img))
cv2.imshow('img',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result
threshold가 100일 경우
threshold가 130일 경우
확율 허프 변환¶
허프변환은 모든 점에 대해서 계산을 하기 때문에 시간이 많이 소요됩니다. 확율 허프변환(Probabilistic Hough Transform)은 이전 허프변환을 최적화 한 것 입니다. 모든 점을 대상으로 하는 것이 아니라 임의의 점을 이용하여 직선을 찾는 것입니다. 단 임계값을 작게 해야만 합니다.
cv2.HoughLinesP() 함수를 이용하는데, 장점은 선의 시작점과 끝점을 Return해주기 때문에
쉽게 화면에 표현할 수 있습니다.
-
cv2.HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap) → lines Parameters: - image – 8bit, single-channel binary image, canny edge를 선 적용.
- rho – r 값의 범위 (0 ~ 1 실수)
- theta – 𝜃 값의 범위(0 ~ 180 정수)
- threshold – 만나는 점의 기준, 숫자가 작으면 많은 선이 검출되지만 정확도가 떨어지고, 숫자가 크면 정확도가 올라감.
- minLineLength – 선의 최소 길이. 이 값보다 작으면 reject.
- maxLineGap – 선과 선사이의 최대 허용간격. 이 값보다 작으며 reject.
Sample Code
import cv2
import numpy as np
img = cv2.imread('images\hough_images.jpg')
edges = cv2.Canny(img,50,200,apertureSize = 3)
gray = cv2.cvtColor(edges,cv2.COLOR_GRAY2BGR)
minLineLength = 100
maxLineGap = 0
lines = cv2.HoughLinesP(edges,1,np.pi/360,100,minLineLength,maxLineGap)
for i in xrange(len(lines)):
for x1,y1,x2,y2 in lines[i]:
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),3)
cv2.imshow('img1',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result
MinLineLength = 100, MaxLineGap = 10
MinLineLength = 100, MaxLineGap = 0