opencv c++ Edge Detection (이미지로부터 경계선 검출)
- 최초 작성일: 2022년 1월 13일(목)
목차
[TOC]
목표
GrayScaling, 노이즈 제거, Binary 이미지화 등 모든 과정들은 오늘 알아보고자하는 Edge Detection을 위한 선행 과정이었다.
영상으로부터 컴퓨터가 물체를 인식하고 처리하기 위해서는 Edge Detection (경계선 검출)이 필수적이다.
opencv 를 활용하여 Edge Detection에 대해서 알아보자.
실습
우선, 대표적인 경계선 검출 기법 중 하나인 Canny Edge Detection에 대해 알아보자. opencv 에서는 Canny Edge detection만을 제공하는 것 같다.
Canny (src, dst, threshold1, threshold2)
- src: 입력 이미지
- dst: 출력 이미지
- threshold1: 하한 임계치 (0~255)
- threshold2: 상한 임계치 (0~255)
자, 그럼 어떤 식으로 함수가 작동하는지 알아보자.
아래와 같이 그림의 색상들이 변화하는 모습을 그래프로 나타낼 수 있다.
어두우면 값이 낮고, 밝으면 값이 높으므로 색이 같을 때는 일정히 가다가 밝아질수록 점점 값이 오르다가 경계선을 만났을 때 툭 떨어진다.
이것처럼 서서히 오르거나 내리거나, 갑작스레 오르거나 내리거나 할 때 이 부분을 경계라고 판단하게 되는 원리이다.
그러면 위에서 보여준 그림과 그래프 말고, 숫자 배열로 나타내보자.
P_x 는 -1 => 0 => 1 이므로, 왼쪽에서 오른쪽으로 상승하는 그래프를 떠올릴 수 있다. 다시 말해, 왼쪽에서 오른쪽으로 움직이다가 경계값을 만나면, 그 값을 기준으로 오른쪽을 흰색(1), 왼쪽을 검정색(0)으로 바꿔주어 흰색 경계선을 표시한다. 반면에, 위에서 아래로 움직이다가 만나는 경계선은 똑같은 값으로 통일하므로 경계선 표시가 안된다.
P_y 는 위에서 아래로 증가하는 형태이므로, 위에서 아래로 내려오면서 만나는 경계선을 흰색으로 표시한다. 마찬가지로 좌우 방향의 경계선은 탐지하지 못한다.
원본 이미지 P_x Edge detection P_y Edge detection
Canny Edge Detection을 간단히 설명하자면, 단계는 아래와 같다.
- Gaussian Filter를 적용하여 노이즈를 제거해준다. (영상을 부드럽게)
- Sobel kernel을 이용해 x, y축에 대한 편미분 벡터를 구한다.
-
이웃하는 픽셀들과 비교하여 변화량의 크기를 판별하여 경계 방향을 찾는다.
-
그렇게 찾은 값들 중에 설정해준 threshold1, threshold2 value를 이용해 추출한다.
- threshold1 보다 작으면 경계가 아니다.
- threshold2 이상이면 강한 엣지
- threshold1 < value < threshold2 : 조건부 (강한 엣지에 연결: 경계 o, 아니면: 경계 x)
소스 코드
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int ac, char** av) {
Mat img = imread("doctor.png", 0); // grayscale image
Mat img_edge;
Canny(img, img_edge, 50, 200);
imshow("original", img);
imshow("img_edge", img_edge);
waitKey(0);
return 0;
}