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)


자, 그럼 어떤 식으로 함수가 작동하는지 알아보자.

아래와 같이 그림의 색상들이 변화하는 모습을 그래프로 나타낼 수 있다.

어두우면 값이 낮고, 밝으면 값이 높으므로 색이 같을 때는 일정히 가다가 밝아질수록 점점 값이 오르다가 경계선을 만났을 때 툭 떨어진다.

image

이것처럼 서서히 오르거나 내리거나, 갑작스레 오르거나 내리거나 할 때 이 부분을 경계라고 판단하게 되는 원리이다.

그러면 위에서 보여준 그림과 그래프 말고, 숫자 배열로 나타내보자.

image

P_x 는 -1 => 0 => 1 이므로, 왼쪽에서 오른쪽으로 상승하는 그래프를 떠올릴 수 있다. 다시 말해, 왼쪽에서 오른쪽으로 움직이다가 경계값을 만나면, 그 값을 기준으로 오른쪽을 흰색(1), 왼쪽을 검정색(0)으로 바꿔주어 흰색 경계선을 표시한다. 반면에, 위에서 아래로 움직이다가 만나는 경계선은 똑같은 값으로 통일하므로 경계선 표시가 안된다.

P_y 는 위에서 아래로 증가하는 형태이므로, 위에서 아래로 내려오면서 만나는 경계선을 흰색으로 표시한다. 마찬가지로 좌우 방향의 경계선은 탐지하지 못한다.


image 원본 이미지 P_x Edge detection P_y Edge detection


Canny Edge Detection을 간단히 설명하자면, 단계는 아래와 같다.

  1. Gaussian Filter를 적용하여 노이즈를 제거해준다. (영상을 부드럽게)
  2. Sobel kernel을 이용해 x, y축에 대한 편미분 벡터를 구한다.

image

  1. 이웃하는 픽셀들과 비교하여 변화량의 크기를 판별하여 경계 방향을 찾는다.

  2. 그렇게 찾은 값들 중에 설정해준 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;
}


결과

image

image