그래디언트 크기만을 기준으로 에지 픽셀을 검출하면 임계값에 민감하고 에지 픽셀이 두껍게 표현되는 문제점이 있다. 그래서 캐니는 자신의 논문에서 다음 세가지 항목을 좋은 에지검출기의 조건으로 제시하였다.
1. 정확한 검출 : 에지를 검출하지 못하거나 또는 에지가 아닌데 에지로 검출하는 확률을 최소화해야 한다.
2. 정확한 위치 : 실제 에지의 중심을 찾아야 한다.
3. 단일 에지 : 하나의 에지는 하나의 점으로 표현되어야 한다.
이 조건을 만족하는 새로운 형태의 에지 검출방법이 캐니 에지 검출기이다. 이는 그래디언트의 크기와 방향을 모두 고려하여 좀 더 정확한 에지 위치를 찾을 수 있다.
첫번째 단계에서 가우시안 필터링을 적용하여 영상의 잡음을 제거한다.
보통 3x3 소벨 마스크를 사용하고, 좀 더 정확한 에지를 찾기 위해 방향을 함께 고려한다.
에지 검출을 위해 단순히 그래디언트크기가 특정 임계값보다 큰 픽셀을 선택할 경우, 에지 근방의 여러 픽셀이 한꺼번에 에지로 선택될 수 있다. 이로 인해 에지가 두껍게 표현되는 것을 방지하기 위해 비최대 억제 과정을 사용한다. 비최대 억제는 그래디언트 크기가 국지적 최대인 픽셀만을 에지 픽셀로 설정하는 기법이다. (local maximum) 상대적으로 국지적 최대가 아닌 픽셀은 에지 픽셀에서 제외하는 것이다.
두개의 임계값을 사용하여 환경변화에 민감해지지 않도록 한다. 높은 임계값과 낮은 임계값을 정하고, 그래디언트 크기가 높은 임계값보다 크면 이 픽셀은 에지로 판단하고, 그래디언트 크기가 낮은 임계값보다 작으면 에지 픽셀이 아니라고 판단한다.
OpenCV에서 캐니 에지 검출 알고리즘이 Canny()함수에 구현되어있다.
void Canny(InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false);
void Canny(InputArray dx, InputArray dy, OutputArray edges,
double threshold1, double threshold2,
bool L2gradient = false);
image : 8비트 입력 영상
dx : 입력영상의 x방향 미분 영상
dy : 입력 영상의 y방향 미분 영상
edges : 출력 에지 영상
threshold1 : 히스테리시스 에지 검출을 위한 첫번째 임계값
threshold2 : 히스테리시스 에지 검출을 위한 두번재 임계값
apertureSize : 그래디언트 계산을 위한 소벨 마스크 크기
L2gradient : 그래디언트 크기 계산 시 L2 norm 을 사용하려면 true를 지정, false이면 l1 사용
void canny_edge() {
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return;
}
Mat dst1, dst2;
Canny(src, dst1, 50, 100); // 높은 임계값 100
Canny(src, dst2, 50, 150); // 높은 임계값 150
imshow("src", src);
imshow("mag", dst1);
imshow("edge", dst2);
waitKey();
destroyAllWindows();
}