본문 바로가기
openCV

[openCV] 선 검출

by _eunji_ 2020. 1. 29.

허프 변환

  • y = ax + b -> b = -ax + y (a : 기울기 b: y절편)
  • 즉, 한 점이 가질 수 있는 모든 직선을 b와 m에 대한 평면에서 하나의 직선으로 표현하는 것
  • 에지 영상에서 가능한 (a,b)의 조합을 구한다.
  • 각 에지 픽셀을 통과하는 직선을 모두 찾은 다음 (a,b)의 조합이 여러번 활용될 경우 그것이 영상에 존재하는 선의 방정식일 확률이 높다.
  • 즉, 에지 픽셀을 통과하는 선들을 찾은 후 겹치는 점이 영상에 존재하는 선이다.

(x,y)가 에지 픽셀일때 각 점을 통과하는 직선의 수는 무수히 많다. 하지만 두 점을 동시에 통과하는 직선은 단 하나. 따라서 두 직선을 동시에 통과하는 (a,b) 조합은 단 하나 존재한다.

  • y = ax + b 라는 식을 활용할 경우 직선이 수직 방향에 가까운 경우 a가 무한대로 수렴하는 문제점 ->  𝜌𝜃 값을 사용
  • 𝜌 : 원점에서 직선에 수선을 내렸을때 수선의 길이
  • 𝜃 : 𝜌와 x축이 이루는 각도 

𝑥𝑐𝑜𝑠𝜃 + 𝑦𝑠𝑖𝑛𝜃 = 𝜌, (𝜌,𝜃) 가 직선이라고 판별

알고리즘

1. 이진 영상으로 변환

2. subdivision 결정, 𝜌𝜃을 변화시킬 간격 정하기 -> 직선을 통과하는 선들이 무수히 많기 때문에 전부 확인하기에 비효율적이므로 𝜌𝜃값을 일정한 간격으로 변화시키면서 직선이 선을 통과하는지 확인

3. accumulator(2차원 배열,0으로 초기화 되어 있음)를 지나는 (𝜌,𝜃)값을 1씩 증가시키고 특정 임계값을 넘는 셀들을 선으로 검출한다.

4. 셀에 해당하는 에지 픽셀들의 연결성을 고려하여 최종적인 직선 검출

accumulator

원 검출

허프 변환을 원에 대해서도 동일하게 적용 가능하다.

(𝑥 − 𝑐1)^2+(𝑦 − 𝑐2)^2= 𝑐3 원의 방정식에서 𝑐1,𝑐2,𝑐3가 반복적으로 사용된다면 파라미터들이 표현하는 원 검출. 

 

 

Houghlines

int main() {
	Mat image, edge, result;
	float rho, theta, a, b, x0, y0;
	Point p1, p2;
	vector<Vec2f> lines;
	image = imread("chess_pattern.png");
	result = image.clone();

	cvtColor(image, image, CV_BGR2GRAY);
	Canny(image, edge, 50, 200, 3);

	//applying Hough Transform to find lines in the image
	//edge: input Mat, lines: output vector of lines
	//1: (rho) distance resolution of the accumulator in pixels / rho의 간격
	//CV_PI/180: (theta) angle resolution of the accumulator in radians / theta의 간격
	//150: (threshold) accumulator threshold parameter / 임계값
	HoughLines(edge, lines, 1, CV_PI / 180, 150); 

	//선 그리기
	for (int i = 0; i < lines.size(); i++) {
		rho = lines[i][0];
		theta = lines[i][1];
		a = cos(theta);
		b = sin(theta);

		x0 = a * rho;
		y0 = b * rho;
		
        //x0,y0 점을 기준으로 기울기를 활용하여 멀리 있는 점을 정의
		p1 = Point(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * a));
		p2 = Point(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * a));

		// 두 점을 양끝점으로 하는 직선을 그리기
		line(result, p1, p2, Scalar(0, 0, 255), 3, 8);
	}
	imshow("Input image", image);
	imshow("edge", edge);
	imshow("Hough Transform", result);
	waitKey(0);
}

Houghlinesp

int main() {
	Mat image, edge, result;
	float rho, theta, a, b, x0, y0;
	Point p1, p2;
	vector<Vec4i> lines;

	image = imread("chess_pattern.png");
	result = image.clone();
	cvtColor(image, image, CV_BGR2GRAY);
	Canny(image, edge, 50, 200, 3);
	//edge: input Mat, lines: output vector of lines
	//1: (rho) distance resolution of the accumulator in pixels
	//CV_PI/180: (theta) angle resolution of the accumulator in radians
	//50: (threshold) accumulator threshold parameter
	//10: (minLineLength) minimum line length. /최소한의 선의 길이
	//300: (maxLineGap) Maximum allowed gap between points on the
	same line to link them / 직선 위 에지들의 최대 허용 간격
	HoughLinesP(edge, lines, 1, CV_PI / 180, 50, 10, 300);

	for (int i = 0; i < lines.size(); i++) {
		Vec4i l = lines[i];
		line(result, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, 8);
	}

	imshow("Input image", image);
	imshow("edge", edge);
	imshow("Hough Transform", result);
	waitKey(0);
}

 

 

 출처 - 컴퓨터 비전 한동대학교 황성수

 http://www.kocw.net/home/cview.do?cid=1b1f5b73413060b5

'openCV' 카테고리의 다른 글

[openCV] 보행자 검출  (0) 2020.01.31
[openCV] 얼굴 검출  (0) 2020.01.31
[openCV] 에지 검출  (0) 2020.01.29
[openCV] 형태학적 연산  (0) 2020.01.29
[openCV] 동영상 분할  (0) 2020.01.18

댓글