허프 변환(Hough Transform)은 컴퓨터 비전, 이미지 처리 및 패턴 인식 분야에서 사용되는 특징 추출 기술들 중 하나 입니다. 1972년에 발표된 오래된 이론으로 처음에는 이미지 내에 직선 성분을 찾기 위한 방법이었지만 추후 원과 타원 추출 방법으로 확장 되었습니다. 현 글에서는 허프 변환을 이용한 직선 추출 방법에 대해 설명하겠습니다.
일반적인 에지 탐색 등을 활용한 직선 성분 추출 시 잡음 등에 의해 중간 중간이 끊겨서 완전한 직선을 탐색하기 어려운 경우가 많습니다. 이 때, 허프 변환을 활용하면 일부 좌표 손실 상황에서도 직선 형태를 강건하게 검출할 수 있다는 장점이 있습니다. 일반적으로 카테시안(데카르트) 좌표계에서 직선식 표현하면 1)와 같으며 기울기 m의 경우 무한대가 나올 수 있어 활용하는데 문제가 될 수 있습니다. 그래서 허프 변환에서는 2)와 같이 극좌표계로 변환하여 직선 성분을 탐색합니다.
1) y = mx + b // m: 기울기, b: y절편
2) r = xcosθ + ysinθ // r: 원점에서 직선까지 수직 거리, θ: 수직선과 x축 사이의 각도

허프 변환은 일부 가려짐이나 잡음에 강한 특성을 가지는 반면 계산량이 많아 질 수 있다는 점과 파라미터 설정이 중요할 수 있습니다. 그림에서처럼 이미지 평면에 점 A, B, C가 존재할 때, 각 점에 대해 각도 별(0~180도)로 거리(r)와 각도(theta)를 구하게 됩니다. 각 점을 지나는 극좌표점을 비교해 보면 60도 일때 가장 비슷한 수치를 얻게되며 파랑색 직선을 얻을 수 있습니다.
OpenCV에서는 직선 탐색을 위한 허프변환에 HoughLines()와 HoughLinesP()의 두 가지 함수를 제공합니다. 전자는 기본 허프 변환이며, 후자는 확률적 허프 변환(Probabilistic Hough Transform)입니다. 파이썬 예제 코드를 통해 파라미터 설정을 참고해보면 이해하기 쉬울 수 있습니다.
lines = cv2.HoughLines(image, rho, theta, threshold)
- image: 8-bit, Canny 등 에지 탐색 된 이진화 이미지
- rho(r): 거리 해상도(1이면 1-pixel 간격)
- theta: 각도 해상도 (0~180), 라디안 값으로 적용
- threshold: 겹치는 점들의 축적값에 대한 임계값
lines = cv2.HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap)
- minLineLength: 직선의 최소 길이
- maxLineGap: 탐색된 직선들 사이에 최대 허용 간격
# Basic Hough Transform -------------------
import cv2
import numpy as np
img = cv2.imread('image.tif')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 150) # 허프 변환
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
# 두 점(x1,y1), (x2,y2)로 직선을 그림
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)
cv2.imshow("Hough Lines", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Probabilistic Hough Transform --------------------------
import cv2
import numpy as np
img = cv2.imread('image.tif')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
# 확률 허프 변환
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 80, minLineLength=50, maxLineGap=10)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("Probabilistic Hough", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
'영상처리 도구' 카테고리의 다른 글
OpenCV Pseudo Color Processing 의사 색상 처리 applyColorMap (3) | 2025.08.03 |
---|---|
OpenCV K-means Clustering 활용하기 (C#) (1) | 2025.07.20 |
머신 비전 TDI Line Scan Camera 원리와 반도체 활용 (1) | 2025.07.10 |
머신 비전 Machine Vision을 위한 렌즈 특성과 용어의 이해 (0) | 2025.07.06 |
머신 비전 Machine Vision을 위한 카메라 렌즈 종류와 선택(2) (0) | 2025.07.02 |