코딩 및 기타/이미지

허프 변환(Hough Transformation)

정지홍 2025. 1. 17. 14:43

식1 , 식2
설명 1
설명 2
원의 매개변수 방정식

허프 변환(Hough Transformation)

  • 이미지에서 특정 모양( 주로 직선이나 원 )을 탐지하는데 사용되는 기법이다.
    • 특징 검출( feature detection )에서 중요한 역할을 한다.
  • 목적
    • 이미지 내에서 직선 , 원 , 타원 등 특정 형태를 찾는데 사용함.
      • 직선 검출 ( 도로 차선 탐지 )
      • 원 검출 ( 동공 검출 , 동전 인식 )
      • 일반 곡선 검출 ( 특정 형상의 곡선 탐지 )
  • 장점
    • 이미지의 잡음에 강함
    • 다양한 모양 검출 가능
  • 단점
    • 매개변수가 많아질수록 누적배열이 많아져서 계산 비용 증가
    • 고해상도 이미지의 경우는 메모리 사용이 크다.
    • 매개변수 이산화 수준에 따라서 검출 정확도에 영향을 받음
  • 활용
    • 도로 차선 검출 , 인간의 동맥 탐지 
  • 직선 검출 원리
    • 1. 직선은 일반적으로 데카르트 좌표계로 표현되나, 기울기가 수직인 경우에는 무한대가 될수 있으니 극좌표계를 사용한다. ( 식 1 , 식 2  , 설명 1 참고 )
    • 2. 이미지 공간에서 직선을 표현하면, 모든 픽셀은 ( x, y )좌표를 가지며, 각 픽셀에서 모든 가능한 직선을 계산하여 허프 공간에 매핑한다. ( 설명 2 참고 )
      • 허프 공간에 매핑시에 동일한 직선을 공유하면, 동일한 ( r , theta )값을 가지니 이 값들이 누적된다.
        즉, 누적된 값이 클수록, 해당 직선을 구성하는 픽셀이 많다는 뜻이다.
    • 3. 위의 과정을 통해 r과 theta를 이산화 한 누적 배열accumulator이 생성된다.
      • 누적 배열에서 높은 값은 이미지 내에서 직선이 존재할 가능성이 높은 것이다.
  • 원 검출 원리
    • 1. 원의 방정식을 사용하여 허프 공간으로 매피 할것이다.
      • 1-1. 이를 위해서 ( a , b , r )이라는 3가지 매개변수를 허프 공간으로 매핑한다.
        • 각 edge 픽셀에서 r값에 따라 가는한 모든 ( a , b )를 계산한다.
        • 누적 배열은 4차원일것이며, 누적값이 큰 지점은 원의 중심과 반지름을 나타낸다.
  • 알고리즘 단계
    • 1. canny , sobel 등을 이용하여 엣지 검출을 한다.
    • 2. 허프 공간을 생성한다.
    • 3. 누적 배열을 업데이트하며 채운다.
    • 4. 최대값 탐색.
    • 5. 이미지에 시각화.

 

cv2.HoughLines( src , rho , theta , threshold , lines , srn=0 , stn=0 , min_theta , max_theta )
  • src : 입력 이미지. 1차원
  • rho: 거리 측정 해상도이며 0~1이다.
    • 값이 작아질수록 해상도가 높아지며 계산량 증가
  • theta: 각도 , 라디안 단위 
  • threshold : 직선으로 판단할 최소한의 동일 개수
    • 작을수록 정확도는 감소하나, 검출 개수는 증가
    • 클수록 정확도는 증가하나 검출 개수는 감소
import numpy as np
import cv2

# 원본을 그냥 2번 읽음
origin = cv2.imread( 'warehouse.jpg' )
img = cv2.imread( 'warehouse.jpg' , cv2.IMREAD_GRAYSCALE )

# canny를 이용하여 엣지 검출
edges = cv2.Canny( img , 220 , 240 )

# 하프선 검출 
lines = cv2.HoughLines( edges , 1 , np.pi/180 , 130 )
print( lines.shape )
print(lines[ 0 ])
print(lines)
# 원본에 그리기 
for line in lines:
    rho , theta = line[ 0 ] # 각도와 r값을 알고 있는 경우 x,y좌표를 구할수있다.
    a , b = np.cos( theta ) , np.sin( theta ) # x  y 좌표를 구한다.
    x0 , y0 = a*rho , b*rho
    cv2.circle( origin ,  ( int(abs( x0 )) , int(abs( y0 )) ), 3 ,  ( 0 , 0 , 255 ) , -1 )
    x1 , y1 = int( x0 + 1000 * ( -b ) ) , int( y0 + 1000 * a )
    x2 , y2 = int( x0 - 1000 * ( -b ) ) , int( y0 - 1000 * a )
    cv2.line( origin , ( x1 , y1 ) , ( x2 , y2 ) , ( 0 , 255 , 0 ) , 1 )

cv2.imshow('hough line', origin)
cv2.waitKey()
cv2.destroyAllWindows()

'코딩 및 기타 > 이미지' 카테고리의 다른 글

segNet  (0) 2025.01.19
VGG 16  (1) 2025.01.17
모폴로지 Morphology  (1) 2025.01.16
U-Net  (0) 2025.01.15
SURF (Speeded-Up Robust Features)  (0) 2025.01.14