[OpenCV] 원 검출 – 허프 그래디언트(Hough gradient)

번 글에서는 허프 변환을 이용하여 원 검출 하는 방법에 대해 알아보겠습니다.

우선 원 검출 방법에 대해 알아보겠습니다. 중심 좌표가 (a, b)이고 반지름이 r인 원의 방정식은 아래와 같습니다.

(x - a)^2 + (y = b)^2 = r^2

위 방정식에서 파라미터는 3개이므로, 3차원 파라미터 공간에서 축적 배열을 정의 후 누적이 많은 위치를 찾아야 합니다.
하지만 이 방식은 메모리와 시간을 많이 필요하므로 허프 그래디언트를 사용합니다.

허프 그래디언트는 아래 두 단계로 이루어져있습니다.

  1. 영상에서 모든 원의 중심 좌표 찾기
  2. 찾은 원의 중심에서 적합한 반지름 구하기

OpenCV에서는 HoughCircles() 함수를 사용하여 원 검출이 가능합니다.
함수에 대한 설명은 아래와 같습니다.

/**
@param image 입력 영상. 8-bit, 싱글채널 그레이스케일 영상
@param circles 출력 원 정보.(벡터)
@param method HOUGH_GRADIENT, HOUGH_GRADIENT_ALT만 사용 가능
@param dp 입력 영상과 축적 배열의 크기 비율
@param minDist 원 중심의 최소 거리
@param param1 캐니 에지 검출 임계값
@param param2 축적 배열에서 원 검출 임계값
@param minRadius 원 검출의 최소 반지름
@param maxRadius 원 검출의 최대 반지름
 */
void HoughCircles(InputArray image,
OutputArray circles,
int method,
double dp,
double minDist,
double param1 = 100,
double param2 = 100,
int minRadius = 0,
int maxRadius = 0 );

샘플 소스는 아래와 같습니다.

Mat src = imread("coins.png");
if (src.empty())
{
	cerr << "image load fail" << endl;
	return;
}

// 그래이스케일로 변환
Mat srcGray;
cvtColor(src, srcGray, COLOR_BGR2GRAY);

// 블러 처리
Mat blurred;
blur(srcGray, blurred, Size(3, 3));

vector<Vec3f> circles;
HoughCircles(blurred, circles, HOUGH_GRADIENT,
			 1/*축적배열 크기 비율*/,
			 50/*인접한 원 중심과의 최소 거리*/,
			 150/*Caany 에지 검출기 높은 임계값*/,
			 30/*축적 배열에서 원 검출을 위한 임계값*/);

Mat dst;
cvtColor(srcGray, dst, COLOR_GRAY2BGR);

for (Vec3f vec : circles)
{
	cout << "Center(" << vec[0] << ", " << vec[1] << ") Radius(" << vec[2] << ")" << endl;
	Point center(cvRound(vec[0]), cvRound(vec[1]));
	int radius = vec[2];

	circle(dst, center, radius, Scalar(0,0,255), 2, LINE_AA);
}
imshow("src", src);
imshow("dst", dst);

waitKey();
destroyAllWindows();

출력 결과는 아래와 같습니다.