본문 바로가기
코딩/OpenCV

[C++ opencv] 허프변환과 확률을 이용한 직선 검출하기, HoughLinesP

by DIYver 2020. 7. 29.

본문 목표

영상처리에 있어서 직선 검출이 필요한 상황이 있다.

이런 경우에 허프변환을 통해서 직선을 검출할 수 있는데,

여기에 확률을 더해서 계산할 수 있다.

기존의 허프변환 방식은 하나하나 다 해보느라 시간이 오래 걸리는 방식이었다면

확률을 이용하여 직선인 것들만 구하므로 보다 빠르다.

허프변환에 확률을 적용한 직선검출을 OpenCV 에서는 어떻게 사용하는지 알아보자.

 

 

키워드 : Hough transform line, HoughLinesP

 

 

 

 

 

 

알아볼 함수 원형

- 확률적용 허프변환 직선검출 ( HoughLinesP )

	vector<Vec4i> linesP;
	HoughLinesP(img_canny, linesP, 1, (CV_PI / 180), 50, 50, 10);

 

HoughLines( src, dst, rho, theta, threshold, min_line_length, max_line_gap )

 

 

  ○ src : 입력할 이미지 변수, Edge detect 된 이미지를 입력해야 함

 

  ○ dst : 허프변환 직선 검출 정보를 저장할 Array 

 

  ○ rho : 계산할 픽셀(매개 변수)의 해상도, 그냥 1을 사용하면 됨

- 변환된 그래프에서, 선에서 원점까지의 수직 거리

 

  ○ theta : 계산할 각도(라디안, 매개변수)의 해상도, 선 회전 각도

- 모든 방향에서 직선을 검출하려면 PI/180 을 사용하면 된다.

 

  ○ threshold : 변환된 그래프에서 라인을 검출하기 위한 최소 교차 수

 

  ○ min_line_length : 검출할 직선의 최소 길이, 단위는 픽셀

 

  ○ max_line_gap : 검출할 선위의 점들 사이의 최대 거리, 점 사이의 거리가 이 값보다 크면 다른 선으로 간주함

 

 

 

 

허프변환 직선검출에 대해서는 간략하게 앞선 포스터에서 다뤄봤었다.

https://diyver.tistory.com/100

 

[C++ opencv] 허프변환을 이용하여 직선 검출하기, HoughLines

본문 목표 영상처리에 있어서 직선 검출이 필요한 상황이 있다. 이런 경우에 허프변환을 통해서 직선을 검출할 수 있는데, OpenCV 에서는 어떻게 사용하는지 알아보자. 키워드 : Hough transform Line 알

diyver.tistory.com

 

허프변환에 대해서 자세히는 다루지 않겠다.

이해한다 하더라도 우리가 계산할 것이 아니므로 대략적인 원리만 알면 된다.

 

 

앞서 다룬 그냥 허프변환과 확률을 고려한 허프변환의 차이는

확률을 적용하냐에 있어서 검출되는 직선이 다르고,

연산속도도 다르다.

 

우선 그냥 HoughLines( ) 는 직선을 검출하게 되고,

확률을 고려한 HoughLinesP( ) 는 선분을 검출한다.

 

HoughLinesP( ) 에서 사용되는 min_line_length 와 max_line_gap 값을 통해서 찾고자 하는 선분을 두 번 걸러주게 된다.

따라서 모든 경우의수를 확인하는 것이 아닌

직선일 수 있는 픽셀들의 좌표만 연산하므로 연산량이 줄어들어 연산속도가 더 빠르다.

 

또한 선분으로 표시해주므로, 직선이 아닌부분에도 직선으로 표시되던 기존의 HoughLines( ) 와는 차이가 있다.

 

 

 

 

 

 

 

코드 테스트 결과

- CODE

#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;


int main(int ac, char** av)
{
	Mat img = imread("lane.png");

	Mat img_gray;
	cvtColor(img, img_gray, COLOR_BGR2GRAY);

	Mat img_canny;
	Canny(img_gray, img_canny, 150, 255);

	vector<Vec4i> linesP;
	HoughLinesP(img_canny, linesP, 1, (CV_PI / 180), 50, 50, 10);

	Mat img_houghP;
	img.copyTo(img_houghP);
	
	Mat img_lane;
	threshold(img_canny, img_lane, 150, 255, THRESH_MASK);

	for (size_t i = 0; i < linesP.size(); i++)
	{
		Vec4i l = linesP[i];
		line(img_houghP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 2, 8);
		line(img_lane, Point(l[0], l[1]), Point(l[2], l[3]), Scalar::all(255), 1, 8);
	}

	imshow("img", img);
	imshow("img_canny", img_houghP);
	imshow("img_lane", img_lane);

	waitKey(0);
	return 0;
}

 

- RESULT

 

lane.png
0.36MB

원본 이미지는 위와 같은 차선 이미지를 사용하였다.

아무래도 직선검출은 자율주행 시스템에서 많이 사용하기 때문에,

적합한 이미지를 찾다가 이 사진을 이용하기로 하였다.

 

이번에는 cvtColor( ) 함수를 이용해서 grayscale 로 변환해 주었다.

grayscale 로 변환해주는 이유는 Edge detection 이 필요하기 때문이다.

 

Canny( ) 함수를 이용해서 Edge detection 을 하였다.

허프변환을 함에 있어서 Edge detection이 된 이미지를 사용하여야 하기 때문이다.

 

여기까지는 기존의 HoughLines( ) 와 동일하고 아래부터 달라진다.

 

 

HoughLinesP( ) 함수를 사용하여 직선 검출한 정보를 저장할 Array를 먼저 생성해준다.

차별점을 두기위해 lines 뒤에 확률의 첫글자인 P 를 붙였다.

 

HoguhLines( ) 와 사용법은 threshold 입력까지 똑같다.

그 뒤로 직선 최소길이와 판별거리를 입력해준다.

 

값은 사용자가 여러가지로 시도하면서 적절한 값을 찾아내야 한다.

 

 

 

검은색 이미지에 직선만 검출한 정보를 띄우기 위해

black mask 를 하나 만들어 주었다.

 

 

원본이미지와 검출된 차선만 표시할 이미지에 검출된 직선을 그려넣는다.

확실히 기존의 허프 변환 직선검출보다 간결한 것을 알 수 있다.

 

 

 

원본에서 찾은 직선 정보들이다.

 

너무 난잡하게 직선들이 검출되어있는 것을 볼 수 있다.

여기서 threshold 값은 50,

min_line_length 값은 50,

max_line_gap 값은 10 으로 설정되어 있는데,

 

threshold 값을 80으로 증가시키고,

직선 최소길이를 100으로 설정,

판별거리를 5로 낮추었다.

 

그 결과는 아래와 같다.

확실히 차선만 검출해준 모습을 확인할 수 있다.

 

좀 더 확실하게 본다면

이러한 차선 검출 이미지를 얻을 수 있었다.

 

이를 통해서 차선주행하는데 확실한 직선을 검출하여 사용하므로

잘못된 판단을 할 가능성을 줄일 수 있다.

 

물론 허프변환이 꼭 좋은 것만은 아니므로,

사용자가 사용해보고 환경에 맞지 않는다면 빠르게 버리는 것도 좋은 방법이다.

 

허프변환은 어찌되었든 연산이 많이 들어가므로, 처리속도가 느려지기 때문이다.

 

 

 

 

 

결론.

 

허프 변환 직선검출은 두가지 방법이 있다.

 

허프 변환 직선 검출에 확률의 개념을 적용하면 조건에 맞는 선분을 검출할 수 있다.

 

직선 검출보다 처리속도가 비교적 빠르다.

 

 

 

 

 

 

 

 

 

 

 

 

도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!

감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^

댓글