[OpenCV] 04-13. Hough Line Transform
🐍Python/OpenCV

[OpenCV] 04-13. Hough Line Transform

728x90
반응형

< Hough Line Transform >

이번 장에서는

  • Hough Transform에 대해서 이해하고
  • 이미지내의 선을 어떻게 탐지하는지 배우고
  • cv2.HoughLines(), cv2.HoughLinesP() 함수

에 대해 알아볼 것이다.

Theory

Hough Transform은 그 모양을 수학적 형태로 나타낼 수 있다면 어떤 형태든 감지하는 인기있는 기법이다. 형체가 조금 부러지거나 일그러져도 감지할 수 있다. 우리는 그것이 어떤 선에 어떻게 작용하는지 볼 것이다!

선은 y=mx+c 또는 파라메트릭 형태로 나타낼 수 있으며, 여기 ρ=xcosθ+ysinθ 식에서, ρ는 원점에서 선까지의 수직 거리, θ는 이 수직선과 시계 반대 방향으로 측정한 수평 축에 의해 형성된 각도이다. 아래 이미지를 보자.



만약 선이 원점 아래로 통과하고 있다면, 이는 양의 ρ 값을 갖고 180도가 안되는 각도를 갖을 것이다. 만약 원점위로 지나간다면 180도 보다 큰 각도를 취하는 대신 각도를 180도 보다 적게 취하고, $\rho를 음의 값이 된다. 모든 수직선은 0도, 수평선은 90도를 가질 것이다.

이제 Hough Transform이 선에 어떻게 작용하는지 보자. 어떤 선이든 이 두 가지 용어로 나타낼 수 있다. (ρ,θ) 그래서 먼저 2D 배열 또는 축압기(accumulator : 연산결과를 임시 보존하거나 누적하는데 사용되는 레지스터)를 만들고(두 개의 매개변수 값을 보유하기 위해),처음에는 0으로 설정된다. 행을 ρ로, 열을 θ로 나타내보자. 배열의 크기는 필요한 정확도에 따라 달라진다. 각도의 정확도가 1이 되려면, 180개의 열이 필요하다. ρ의 경우, 가능한 최대 거리는 이미지의 대각선 길이이다. 따라서 한 픽셀의 정확도를 고려하면, 행의 수는 이미지의 대각선 길이가 될 수 있다.

가운데 수평선이 있는 100x100 이미지를 생각해보자. 줄의 첫 점을 잡아보자. (x,y)가 될 것이다. 이제 선 방정식에, θ=0,1,2,...,180값을 넣고, ρ를 확인해보자. 모든 (ρ,θ) 쌍에 대해, 해당 좌표셀에서 축압기에 있는 값을 1씩 증가시킨다. 그래서 현재 축압기에서 다른 셀들과 함께 (50,90)셀도 1이다.

이제 두 번째 점을 선위에 짚어보자. 위와 같이, (ρ,θ)에 해당하는 셀의 값을 증가시킨다. 이번에는 (50,90)셀을 2라고 하자. 실제로 하는 일을 (ρ,θ) 값을 투표하는 것이다. 이 과정을 라인상의 모드 ㄴ점에 대해 계속 진행한다. 각 지점에서, (50,90)은 증가하거나 투표되고, 다른 셀들은 투표될 수도 그러지 않을 수도 있다. 이렇게 하면 마지막에 (50,90)이 최대 투표를 얻게 된다. 그래서 최대표를 얻기 위해 축압기를 찾아보면 (50,90) 값을 얻을 수 있는데, 이 그림에서는 원점에서 50도 떨어진 곳에 선이 나있고, 각도는 90도라고 되어있다. 아래 GIF를 보자.


이는 선에 대해 Hough Transform이 어떻게 작동하는지를 보여준다. 이는 간단한데, Numpy를 사용하여 구현할 수도 있다. 아래 이미지는 축압기를 보여준다. 밝은 지역들은 이미지내에서 선이 있을 가능성의 파라미터를 나타낸다.


Hough Transform in OpenCV

위에 설명된 모든 것은 OpenCV에 내장된 cv2.HoughLines()에 대한 것이다. 이는 단순하게 (ρ,θ) 값의 배열을 반환한다. ρ는 픽셀에서 측정되고, θ는 호도(radians)에서 측정된다. 첫 번째 파라미터인, 입력 이미지는 이원 이미지여야 하므로, Hough Transform을 적용하기 전에 임계값을 적용하거나 canny edge detection을 적용해야한다. 두 번째와 세 번째 파라미터는 각각 ρ,θ 정확도이다. 네 번째 인자는 임계값으로, 선으로 판단되기 위해 얻어야 하는 최소한의 표를 말한다. 투표의 수는 선의 점 갯수에 따라 다르다는 것을 기억해야한다. 따라서 감지해야할 선의 최소 길이를 나타낸다.

import cv2
import numpy as np

img = cv2.imread('./images/sdoku.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize=3)

lines = cv2.HoughLines(edges,1,np.pi/180,200)

for line in lines:
    rho,theta = line[0]
    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)
cv2.imwrite("HoughLine-0.jpg",img)

아래 결과를 보자


Probabilistic Hough Transform

Hough Transform 내에서, 두 개의 인자가 있는 선에 대해 많은 계산이 필요하다는 것을 알 수 있다. 확률론적 Hough Transform은 우리가 본 Hough Transform의 최적화된 버전이다. 이는 모든 점을 고려하지 않고, 임의의 점 하위 집합만을 취한다. 이는 선 탐지에 충분하다. 그리고 임계값을 낮춘다. hough 공간에서 Hough Transform과 Probabilistic Hough Transform을 비교하는 아래 이미지를 참조하자.




OpenCV 구현은 Matas, J. 및 Galambos, C. 및 Kittler, J.V.의 점진적 확률론적 Hough Transform을 사용하여 Robust Detection of Lines에 기초한다. 사용된 함수는 cv2.HoughLinesP()이다. 여기는 두 개의 새로운 인자가 등장한다.

  • minLineLength - 선의 최소 길이이다. 이보다 짧은 선분은 버려진다.
  • maxLineLength - 단일 선으로 처리하기 위해 선분 간에 허용되는 최대 간격이다.

가장 좋은 것은, 두 개의 선 끝점을 직접적으로 반환한다는 것이다. 이전의 경우에는 선의 매개변수를 얻었을 뿐, 모든 점을 찾아야 했다. 여기서는 모든 것이 직접적이고 간단하다.

import cv2
import numpy as np

img = cv2.imread('./images/sdoku.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize=3)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
for line in lines:
    x1,y1,x2,y2 = line[0]
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv2.imwrite('HoughLine-1.jpg',img)



728x90
반응형