본문 목표
영상처리에 있어서 원을 검출할 상황이 종종 발생한다.
이런 경우에 허프변환을 이용하여 원을 검출해낼 수 있다.
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
원본 이미지로 다양한 원, 타원, 화살표, 네모가 섞여있다.
원본 이미지를 흑백으로 불러오고,
노이즈 제거를 우선적으로 해준다.
꼭 medianBlur 를 사용하지 않아도 된다.
검출된 원을 표시할 이미지를 생성해주고,
원본 이미지의 정보를 복붙해준다.
앞서 말한대로 검출된 원의 정보를 저장시킬 변수를 만들어주고,
HoughCircles( ) 함수를 통해서 원을 검출해준다.
검출한 원의 정보들을 통해서 이미지에 원과 해당 원의 중심을 표시해준다.
결과 이미지는 위와 같이 나온다.
타원의 경우 min_dist 값을 100으로 두었기 때문에
원이 두개로 검출되지 않고, 하나로 검출되었다.
타원의 경우 깔끔하게 검출이 되지 않을 수 있음을 확인할 수 있었다.
parameter2 값이 너무 작으면 거짓원이 검출될 수 있다고 했는데,
그에 대한 테스트를 진행해 보았다.
당장 원래의 값 35에서 30으로 5만 낮췄을 때의 결과이다.
보다시피 거짓원이 여러개 검출된것을 볼 수 있다.
반대로 값을 너무 높이면
작은 원은 검출을 못하기도 하므로, 사용자가 값을 여러가지 시도해봐야 한다.
결론.
OpenCV에서 허프변환을 이용해 원을 검출할 수 있다.
원을 검출하기 위해서 다양한 정보값을 필요로 한다.
제일 민감한 값은 parameter2 값이므로, 많은 시행착오가 필요하다.
도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!
감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^
'코딩 > OpenCV' 카테고리의 다른 글
[C++ opencv] 웹캠으로 실시간 HSV 값 추출하기 (4) | 2020.10.18 |
---|---|
[C++ opencv] 이미지에 텍스트 넣기 (2) | 2020.10.17 |
[C++ opencv] 허프변환과 확률을 이용한 직선 검출하기, HoughLinesP (0) | 2020.07.29 |
[C++ opencv] 허프변환을 이용하여 직선 검출하기, HoughLines (0) | 2020.07.29 |
[C++ opencv] 이미지의 pixel 데이터 접근하기, 색상 정보 확인하기 (7) | 2020.07.28 |
댓글