본문 바로가기

study/영상처리 & opencv

[opencv] 직선 검출(Line Detection)

참고 출처 : https://076923.github.io/posts/Python-opencv-28/
https://opencv-python.readthedocs.io/en/latest/doc/25.imageHoughLineTransform/imageHoughLineTransform.html   
https://ko.wikipedia.org/wiki/%ED%97%88%ED%94%84_%EB%B3%80%ED%99%98

 

직선 검출 알고리즘

: 허프 변환(Hough Transform)을 활용 (위 출처의 이론적인 설명이 자세하게 나와 있습니다 )

 

그냥 정리한다고 끄적끄적.. 극좌표 방정식 증명 해보고 싶었는데 못했다.. 수학 실력 어디로...
출처 : https://en.wikipedia.org/wiki/Hough_transform

 

위의 사진처럼 3개의 점에 대해서 원점에서 각 점까지의 거리를 𝜃, r로 표현할 수 있다.

 

 

대략적으로 그래프로 그려보기 (sin파 그래프로 표현된다고 한다.)

 

이 곡선은 각 점(x, y)에 대해서  r=xsinθ+ycosθ을 만족한다.

 

허프 변환은 OpenCV의 cv2.HoughLines() 함수로 구현되어 있다.

 

void cv::HoughLines	(	
 InputArray 	image, //검출 이미지
 OutputArray 	lines, //line 반환
 double 	rho,  //거리 r (0 ~ 1)
 double 	theta, //각도 𝜃 (단위 : 라디안)
 int 	threshold, //임계값(문턱치)(숫자가 작을수록 많은 선 검출, 정확도 하락)
 double 	srn = 0, //srn과 stn은 멀티 스케일 허프 변환에 사용, 선 검출에서는 사용X
 double 	stn = 0,
 double 	min_theta = 0, //검출을 위해 사용할 최소 최대 각도
 double 	max_theta = CV_PI 
)		
//Python:
//lines	=	cv.HoughLines(	image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]]	)

threshold : 같은 직선에 몇개의 점이 등장해야 직선으로 판단할 지에 대한 최소 갯수

srn과 stn : 거리와 각도에 대한 약수를 의미한다. 두 값이 모두 0이면 표준 허프 변환이 적용되고 하나라도 0이 아니라면 멀티 스케일 허프 변환이 적용된다.

 

이에 대한 예제 코드와 사용되는 이미지는 076923.github.io/posts/Python-opencv-28/ 에서 참고하여 사용하였다.

그리고 코드는 colab환경(python)에서 진행하였다.

 

 

canny edge 검출 사용 (전처리)

 

Canny edge 검출기

: 낮은 검출 오류율, 에지 위치 오류 최소화, 단일 응답(하나의 edge에서 하나의 화소만 edge로 검출)

1. 가우시안 필터링을 통한 잡음 제거

2. 에지 크기와 방향 계산 -> Sobel filter를 사용

 

 

3. 비최대치 억제(non-maximum suppression)

- 주변의 edge와 비교해서 더 큰 크기를 가지기 않는 edge를 제거

즉, 주변보다 더 큰 크기를 갖는 edge만 남긴다. 주변은 에지의 방향에 따라 결정된다.

ex) 90도 기준 예시

(y, x-1) (y, x)(y, x+1)

4. 이력 문턱치 처리(hysteresis thresholding)

- 두 개의 문턱치(큰 문턱치, 작은 문턱치)를 사용하여 처리 수행

큰 문턱치보다 큰 크기를 갖는 edge 살리고 작은 문턱치보다 작은 크기의 edge 제거

큰 문턱치와 작은 문턱치 사이의 edge는 큰 문턱치보다 큰 크기를 갖는 edge들과 연결되어 있으면 살아남고 그렇지 않으면 제거된다.

 

 

HoughLInes 함수 사용하여 lines 구하기 (반환값은 r, 𝜃)

 

 

 

검출된 line 그려주기

 

line은 거리와 각도로 반환되기 때문에 이것을 활용하여 다시 직선의 방정식 형태로 구성 후 이미지 위에 표현해준다.

x=rcosθ, y=rsinθ을 활용하여 x0, y0의 좌표를 구한다.

 

허프 변환 함수는 가장 직선일 가능성이 높은 거리와 각도를 검출해주기 때문에 (x0, y0)을 직선의 방정식 선분을 따라 평행이동 시켜 선을 그려주게 된다. 

! 여기서 원점의 기준이 이미지 중앙인지 아니면 모서리 한부분인지는 정확히 알지 못하겠다.

(x1, y1), (x2, y2)를 구해줄 때 사용하는 식에서 scale은 그림 끝에서 끝까지 그리기 위한 큰 수로 꼭 위의 코드처럼 구하지 않아도 되고 임의로 큰 수를 넣어도 상관없다고 이해했다. a와 -b를 곱해줌으로써 (x1, y1), (x2, y2)이 (x0, y0)을

평행이동한 점으로 계산해주게 된다.

 

 

따라서 이렇게 진행한 결과 사진은 아래와 같다.

 

멀티 스케일 허프 변환 결과

 

이 알고리즘을 보안하여 나온 것으로 점진성 확률적 허프 변환도 있다고 한다.