📌 Intro
이미지에서 선레이저로 된 직선을 찾는 방법을 알아보다 허프변환에 대해 알게 되었다. 허프변환은 이미지에서 모양을 찾는 방법으로 가장 잘 알려져있다. 이 방법을 이용하면 이미지의 형태를 찾거나, 누락되거나 깨진 영역을 복원할 수도 있다고 한다.
허프변환의 간단한 이론적인 내용과 사용 방법에 대해 정리해보려 한다.
📌 이론
하나의 점을 지나는 무수한 직선의 방적식은 y=mx+c로 표현할 수 있고, 이를 삼각함수를 통해 변형하면 r = 𝑥 cos𝜃 + 𝑦 sin𝜃 로 표현할 수 있다. 각 점(x,y)에 대해서 삼각함수를 이용하여 𝜃 값을 1 ~ 180까지 변화를 하면서 원점에서 (x,y)까지의 거리(r)을 구한다. 그러면 (𝜃, r)로 구성된 180개의 2차원 배열을 구할 수 있다. 세 점에 대해 위 과정을 반복한다. 그러면 아래와 같은 그림과 배열을 얻을 수 있다.
얻은 배열을 그래프로 나타내면 다음과 같다.
3개의 그래프가 만나는 점이 직선일 확률이 높은 점이다. 즉, 𝜃가 60이고, 거리가 80인 직선의 방정식을 구할 수 있게 되는 것이다.
📌 HoughLines, HoughLinesP
위에서 설명한 내용이 openCV의 HoughLines()함수로 구현되어 있다. HoughLines()함수는 모든 점에 대해 허프변환을 하는 것이고, HoughLinesP()함수는 허프변환을 최적화한 방법으로 임의의 점을 이용하여 직선을 찾는 방법이다.
그렇다면 두 함수의 파라미터에 대해 더 알아보자.
- cv2.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]])
- image : single channel binary image, canny edge를 적용할 수 있다.
- rho : r값의 범위(0~1 실수)
- theta : 𝜃값 범위(0~180 정수)
- threshold : 만나는 점의 최소 개수, 값이 작으면 많은 선이 검출되고 정확도가 떨어진다. 값이 크면 적은 선이 검출되고 정확도가 높아진다.
- cv2.HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap)
- image : single channel binary image, canny edge를 적용할 수 있다.
- rho : r값의 범위(0~1 실수)
- theta : 𝜃값 범위(0~180 정수)
- threshold : 만나는 점의 최소 개수, 값이 작으면 많은 선이 검출되고 정확도가 떨어진다. 값이 크면 적은 선이 검출되고 정확도가 높아진다.
- minLineLength : 선의 최소 길이, 이 값보다 작으면 반환되지 않는다.
- maxLineGap : 선과 선 사이의 최대 간격, 이 값보다 작으면 반환되지 않는다.
📌 소스코드
import cv2
import numpy as np
# 이미지 로드
img = cv2.imread('test.jpg')
# 엣지 검출
edges = cv2.Canny(img,50,150, apertureSize=3)
minLineLength = 100
maxLineGap = 10
# 확률 허프 변환 적용
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
if lines is None:
print("no lines")
else:
for line in lines:
# 검출된 선 그리기
x1,y1,x2,y2 = line[0]
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
# 확인
cv2.imshow('img by Hough', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
📌 결과
cv2.HoughLinesP() 함수는 결과로 직선의 시작점과 끝점을 반환하기 때문에 쉽게 직선을 그려줄 수 있다. 아래는 원본 이미지와 허프변환을 이용하여 직선을 붉은색으로 그려준 이미지다. 대부분의 직선을 잘 찾은 것을 확인할 수 있다.
📌 참고
[1] https://wjunsea.tistory.com/60
[2] https://opencv-python.readthedocs.io/en/latest/doc/25.imageHoughLineTransform/imageHoughLineTransform.html