중심좌표가 (a, b) 이고 반지름이 r인 원의 방정식은 다음과 같다.
(x - a)^2 + (y - b)^2 = r^2
원의 방정식은 파라미터가 세개이고, 허프변환을 그대로 적용하려면 3차원 파라미터 공간에서 축적배열을 정의하고 가장 누적이 많은 위치를 찾아야 한다. 그러나 이는 너무 복잡하므로 일반적인 허프 변환대신 허프 그래디언트 방법을 사용하여 원을 검출한다.
허프 그래디언트 방법은 두가지 단계로 구성된다. 첫번재 단계는 영상에 존재하는 모든 원의 중심 좌표를 찾고, 두번재 단계에서는 검출된 원의 중심으로 부터 원에 적합한 반지름을 구한다. 원의 중심 좌표를 찾는 과정에서 축적 배열이 사용된다. 이 축적배열에서는 입력 영상과 동일한 xy좌표 공간에서 2차원 배열로 만들어 입력 엿앙의 모든 에지 픽셀에서 그래디언트를 구하고, 그래디언트 방향을 따르는 직선상의 축적 배열값을 1씩 증가한다.
위 그림은 허프 그래디언트 방법을 이용하여 원의 중심을 검출하는 과정이다.
OpenCV 에서는 HoughCircles()함수를 사용하여 원을 검출할 수 있다.
void HoughCircles(InputArray image, OutputArray circles,
int method, double dp, double minDist,
double param1 = 100, double param2 = 100,
int minRadius = 100, int maxRadius = 0);
image : 입력영상 (그레이스케일 영상)
circle : 검출된 원 정보를 저장할 출력 벡터
method : Hough_GRADIENT 만 지정 가능
dp : 입력 영상과 축적배열의 크기 비율
minDist : 인접한 원 중심의 최소거리
param1 : Canny 에지 검출기의 높은 임계값
param2 : 축적 배열에서 원검출을 위한 임계값
minRadius : 검출할 원의 최소반지름
maxRadius : 검출한 원의 최대반지름
void hough_circles()
{
Mat src = imread("coins.png", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return;
}
Mat blurred;
blur(src, blurred, Size(3, 3));
vector<Vec3f> circles;
HoughCircles(blurred, circles, HOUGH_GRADIENT, 1, 50, 150, 30);
Mat dst;
cvtColor(src, dst, COLOR_GRAY2BGR);
for (Vec3f c : circles) {
Point center(cvRound(c[0]), cvRound(c[1]));
int radius = cvRound(c[2]);
circle(dst, center, radius, Scalar(0, 0, 255), 2, LINE_AA);
}
imshow("src", src);
imshow("dst", dst);
waitKey(0);
destroyAllWindows();
}