본문 바로가기
코딩/OpenCV

[C++ opencv] 허프변환 원 검출하는 방법, HoughCircles

by DIYver 2020. 7. 29.

본문 목표

영상처리에 있어서 원을 검출할 상황이 종종 발생한다.

이런 경우에 허프변환을 이용하여 원을 검출해낼 수 있다.

OpenCV에서 어떻게 허프변환을 이용하여 원을 검출할 수 있는지 알아보자.

 

 

키워드 : HoughCircles

 

 

 

 

 

알아볼 함수 원형

- 허프변환 원 검출 ( HoughCircles )

	vector<Vec3f> circles;
	HoughCircles(img_houghC, circles, HOUGH_GRADIENT, 1, 100, 50, 35, 0, 0);

 

HoughCircles( src, dst, method, dp, min_dist, parameter1, parameter2, min_Radius, max_Radius

 

  ○ src : 입력할 이미지 변수, grayscale 의 이미지를 입력해야 함

 

  ○ dst : 허프변환 원 검출 정보를 저장할 Array , 원의 중심의 정보가 저장됨

 

  ○ method : 원을 검출하는 방법, HOUGH_GRADIENT 를 사용하면 됨

 

  ○ dp : 이미지 해상도,

- 값이 1이면 원본 해상도를 사용함, 왠만하면 1을 쓰면 됨

- 값이 2이면 절반 해상도를 사용함

 

  ○ min_dist : 검출할 원의 최소 거리

- 원의 반지름이 아니라, 검출할 원의 밀도를 이 값으로 조절할 수 있음

- 원이 오밀조밀하게 모여있다면 이 값이 작아야함

- 원이 넓게 골고루 퍼져있다면 오검출이 되지않게 적당히 높게 설정해야 함

 

  ○ parameter1 : Canny edge detection 에서의 높은 threshold 값

- HoughCircles 는 grayscale 이미지를 입력받아서 자체적으로 Canny 엣지 검출을 실시함

- Canny 엣지 검출에는 2개의 threshold 값이 존재하는데, 이 값은 큰 값을 뜻함

- 작은 값은 자동으로 0.5배로 적용됨

 

  ○ parameter2 : 원 검출을 위한 정보로, accumulator의 threshold 값

- 너무 작으면 거짓 원이 검출 됨

- 가장 큰 accumulator의 값이 가장 먼저 원으로 반환됨

 

  ○ min_Radius : 검출 될 원의 최소 반지름

- 모든 원을 검출하려면 0을 입력

 

  ○ max_Radius : 검출 될 원의 최대 반지름

- 모든 원을 검출하려면 0을 입력

- 음수 값을 입력하면 원의 중심만 반환됨

 

 

 

 

 

 

기존의 HoughLines( ) 보다 정보를 많이 필요로 한다.

하지만 크게 어려운 부분은 없으므로, 이해만 한다면 충분하다.

 

우선 검출 된 원의 정보들을 저장할 변수로는

vector<Vec3f> 벡터 자료형을 이용해야한다.

3차원임을 알 수 있는데, 쉽게 말하자면 원 하나에 데이터가 3개가 저장된다는 뜻이다.

중심 좌표로 a, b 가 필요하고, 반지름 값 r 이 저장된다.

 

사용자가 조심해서 사용해야할 정보들은

min_dist 와 parameter1, parameter2 값이 되겠다.

위의 3가지 정보로 인해서 원이 정상적으로 검출될 수 있지만,

값을 잘 못 넣으면 원이 이상하게 검출된다.

 

 

 

 

 

 

코드 테스트 결과

- CODE

#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;

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

	medianBlur(img, img, 5);

	Mat img_houghC;
	img.copyTo(img_houghC);
	
	vector<Vec3f> circles;
	HoughCircles(img_houghC, circles, HOUGH_GRADIENT, 1, 100, 50, 35, 0, 0);
	
	for (size_t i = 0; i < circles.size(); i++)
	{
		Vec3i c = circles[i];
		Point center(c[0], c[1]);
		int radius = c[2];

		circle(img_houghC, center, radius, Scalar(0, 255, 0), 2);
		circle(img_houghC, center, 2, Scalar(0, 0, 255), 3);
	}


	imshow("img_houghC", img_houghC);
	waitKey(0);
	return 0;
}

 

- RESULT

circles.PNG
0.09MB

원본 이미지로 다양한 원, 타원, 화살표, 네모가 섞여있다.

 

 

원본 이미지를 흑백으로 불러오고,

노이즈 제거를 우선적으로 해준다.

꼭 medianBlur 를 사용하지 않아도 된다.

 

검출된 원을 표시할 이미지를 생성해주고,

원본 이미지의 정보를 복붙해준다.

 

앞서 말한대로 검출된 원의 정보를 저장시킬 변수를 만들어주고,

HoughCircles( ) 함수를 통해서 원을 검출해준다.

 

검출한 원의 정보들을 통해서 이미지에 원과 해당 원의 중심을 표시해준다.

 

 

결과 이미지는 위와 같이 나온다.

타원의 경우 min_dist 값을 100으로 두었기 때문에 

원이 두개로 검출되지 않고, 하나로 검출되었다.

 

타원의 경우 깔끔하게 검출이 되지 않을 수 있음을 확인할 수 있었다.

 

 

 

 

 

 

 

 

parameter2 값이 너무 작으면 거짓원이 검출될 수 있다고 했는데,

그에 대한 테스트를 진행해 보았다.

당장 원래의 값 35에서 30으로 5만 낮췄을 때의 결과이다.

 

보다시피 거짓원이 여러개 검출된것을 볼 수 있다.

 

반대로 값을 너무 높이면

작은 원은 검출을 못하기도 하므로, 사용자가 값을 여러가지 시도해봐야 한다.

 

 

 

 

 

 

 

결론.

 

OpenCV에서 허프변환을 이용해 원을 검출할 수 있다.

 

원을 검출하기 위해서 다양한 정보값을 필요로 한다.

 

제일 민감한 값은 parameter2 값이므로, 많은 시행착오가 필요하다.

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

댓글