해당 포스팅은 OpenCV 4로 배우는 컴퓨터 비전과 머신러닝 (황선규 저)를 보고 공부하며 개인적인 용도를 위해 정리한 글이다.
에지 검출
- 영상에서의 에지란 한 쪽 방향으로 픽셀값이 급격하게 바뀌는 부분을 가르킨다.
- 보통 픽셀값의 변화량에 따른 미분값을 통해 에지를 검출한다.
- 어두운 영역에서 급격하게 밝아지거나, 반대로 밝은 영역에서 급격하게 어두워지는 부분을 의미하며, 객체간의 경계에서 에지가 발생한다.
- 에지는 미분과 그래디언트를 이용하여 변화율이 큰 픽셀을 검출하는 방법을 이용한다.
미분 (Derivative)
- 함수 혹은 데이터의 변화율을 의미한다.
- 1차원 연속 함수 $f(x)$에 대한 미분 수식은 다음과 같다.
- \[f' = \frac{df}{dx} = \lim\limits_{\triangle x \ to 0}\frac{f(x + \triangle x) - f(x)}{\triangle x}\]
- $\triangle x$는 $x$의 변화량을 의미한다. 변화량이 무한히 $0$에 가까워질 때 함수값의 변화량을 미분이라고 정의한다.
- 함수값이 증가하는 위치에서는 미분값은 양수, 감소하는 위치에서는 음수를 가지며 일정한 구간에선 $0$에 근접한다.
영상에서의 미분값 구하기
- 영상으로부터 미분을 계산하려면 두 가지의 특징을 고려해야한다.
- 영상이 2차원 평면에서 정의 된 함수라는 것.
- 영상이 정수 단위 좌표에 픽셀이 나열 되어있는 이산함수라는 것.
1차원 이산함수에서의 미분
- 일련의 데이터가 순서대로 나열 되어있는 경우 미분 근사화 방법을 이용해 변화량을 측정 가능하다.
- 전친 차분 (Forward derivative) $\frac{dI}{dx} \cong \frac{I(x + h) - I(x)}{h}$
- 후진 차분 (Backward derivative) $\frac{dI}{dx} \cong \frac{I(x) - I(x - h)}{h}$
- 중앙 차분 (centered derivative) $\frac{dI}{dx} \cong \frac{I(x + h) - I(x - h)}{2h}$
- $I(x)$은 1차원 이산함수, $h$는 픽셀간의 거리이며, 픽셀 최소 간격인 $1$을 $h$ 값으로 정해준다.
- 이론 상 중앙차분이 오류가 가장 적게 발생하기 때문에 영상에서 미분을 계산해야 할 때 가장 많이 사용한다.
2차원 평면에서의 미분
- 영상은 2차원 평면에서 정의 된 함수이기 대문에 영상에서 변화량을 측정하기 위해선 가로세로 방향으로 각각 미분해줘야한다.
- 2차원 영상 $I(x, y)$를 가로 방향으로 미분한다는 것은 $y$축 좌표는 고정한 채로 $x$축 방햐으로만 미분 근사하는 것을 의미한다.
- 이를 $x$축 방향으로 편미분 (partial derivative)라고 하며, $I_x$로 표현한다.
- 마찬가지로 $x$축 좌표를 고정한채 $y$축 방향으로만 미분 근사하는 것을 $y$축 방향으로의 편미분이라 부르며 $I_y$로 표현한다.
- 수식은 다음과 같다.
- \[\begin{cases} I_x = \frac{\partial I}{\partial x} \cong \frac{I(x + 1, y) - I(x - 1, y)}{2} \\ I_y = \frac{\partial I}{\partial y} \cong \frac{I(x, y + 1) - I(x, y - 1)}{2} \\ \end{cases}\]
- 중앙차분을 이용한 미분 근사는 마스크 연산을 통해 쉽게 구현 할 수 있다.
- 2차원 영상을 $x, y$축 방향으로 각각 편미분을 수행하는 마스크 필터는 다음과 같다.
- $x$축 - $\begin{bmatrix} -1 & 0 & 1 \end{bmatrix}$
- $y$축 - \(\begin{bmatrix} -1 \\ 0 \\ 1 \end{bmatrix}\)
- 2차원 영상을 $x, y$축 방향으로 각각 편미분을 수행하는 마스크 필터는 다음과 같다.
- 입력 영상에서 편미분을 진행 할 때 시각적으로 쉽게 분석하기 위해선 미분한 값에 $128$을 더한 후 $0$부터 $255$ 사이의 정수로 형변환한다.
- 픽셀값의 변화가 없는 부분은 회색으로, 큰 부분은 변화량에 따라 각각 흰색과 검은색으로 보인다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "opencv2/opencv.hpp"
#include <iostream>
void sobel_derivative();
int main(void)
{
sobel_derivative();
return 0;
}
void sobel_derivative()
{
cv::Mat src = cv::imread("path/to/src", cv::IMREAD_GRAYSCALE);
cv::Mat mx = cv::Mat_<double>({1, 3}, {-1 / 2.f, 0, 1 / 2.f}); // x축 마스크 필터
cv::Mat my = cv::Mat_<double>({3, 1}, {-1 / 2.f, 0, 1 / 2.f}); // y축 마스크 필터
cv::Mat dx, dy;
cv::filter2D(src, dx, -1, cv::Point(-1, -1), 128); // x축 편미분
cv::filter2D(src, dy, -1, cv::Point(-1, -1), 128); // y축 편미분
std::vector<cv::Mat> v({src, dx, dy});
cv::Mat res;
cv::hconcat(v, res);
cv::imshow("results", res);
cv::waitKey(0);
cv::destroyAllWindows();
}
그래디언트 (Gradient)
- 2차원 공간에서 정의 된 함수 $f(x, y)$가 있을 때 이 함수의 각 축에 대한 미분을 벡터로 표현한 것이다.
- 수식은 다음과 같다.
- $\nabla f = \begin{bmatrix} f_x \ f_y \end{bmatrix} = f_x i + f_y j$
- 그래디언트는 벡터이기 때문에 크기 (magnitude) 와 방향 (phase) 성분으로 표현 가능하다.
- 벡터의 방향은 픽셀값의 변화량이 가장 큰 방향을 나타낸다.
- $\theta = \tan^{-1}\begin{pmatrix} \frac{f_y}{f_x} \end{pmatrix}$
- 벡터의 크기는 변화율의 크기를 나타내는 척도로 생각 할 수 있다.
- $\lVert \nabla f \rVert = \sqrt{ {f_x}^2 + {f_y}^2 }$
- 벡터의 방향은 픽셀값의 변화량이 가장 큰 방향을 나타낸다.
- 2차원 영상에서 에지를 찾는 기본적인 방법은 그래디언트 크기가 특정 값보다 큰 위치를 찾는 것이다.
- 에지 여부를 판단하기 위해 기준이 되는 값을 임계값 (threshold) 라고 한다.
- 영상의 특성에 따라 다르게 적용시키며 보통은 사용자의 경험에 의해 결정 된다.
- 임계값이 높으면 차이가 급격하게 변하는 에지 특성을 검출한다.
- 임계값이 낮으면 차이가 조금만 변해도 특성을 검출시킨다.
- 영상의 특성에 따라 다르게 적용시키며 보통은 사용자의 경험에 의해 결정 된다.