티스토리 뷰

영상처리/OpenCV

10. Directional Filter(Sobel)

빠리빵 2019. 4. 27. 11:31

가끔씩 영상에서 방향성을 계산해야하는 상황이 생긴다. 예를들어 영상에서 두 픽셀 사이에 값을 interpolation 하는 상황이 생길 수 있는데(image sensor level), 방향성을 갖는 부분에서 이전에 언급했던 bilinear interpolation을 한다거나, 일반적인 interpolation 방식을 사용하게 되는 경우 화질적인 측면에서는 눈에 잘 보이는 artifact들이 생겨날 수 있다. 영상에서 방향성이 있는 부분이라면 그 방향성을 따져서 처리를 해줘야 하기 때문이다.(대각선으로 gradation이 있는 선을 생각해보자, 대각선 방향 line을 따라서 interpolation을 해야하지 주위 픽셀을 모두 사용하면 artifact들이 생겨날 수 있음.) 따라서 이번 시간에는 영상에서 방향성을 얻는 방법에 대해 알아본다. 

 

openCV에서 제공해주는 함수로는 Sobel 함수가 존재한다. edge detection을 위한 high pass filter이며, 간단한 사용법은 위와 같다. 입력, 출력, data type, 방향, kernel size, scale 및 offset이 parameter로 들어간다. 

 

Sobel operator는 edge detection filter이며, 기본적으로는 3x3 kernel을 사용한다. 영상은 2D이기 때문에 방향성 또한 수직과 수평방향 2가지로 진행한다. (image sensor level에서는 대각선으로 필요로 하는 경우도 있다.) 수학적 용어로 이러한 계산을 gradient라 하며 수식은 아래와 같다. 

 

horizontal 방향의 계산 예제이다. kernel의 weight를 생각해보면 결과과 음수가 나올 수 있으며, 입력 range를 벗어날 수 있다. 따라서 scale, offset을 활용하여 원하는 형식으로 output range를 지정해야 한다. 위의 경우에는 scale은 0.4, offset은 128이며 이 경우엔 기준이 128이 된다고 생각하면 되겠다. (방향은 반대 방향으로도 존재할 수 있다.)

 

Sobel function으로 horizontal, vertical 방향으로 계산을 하였다. 우리가 원하는 것은 해당 픽셀에서 horizontal과 vertical을 혼합한 방향성을 얻기 원하기 때문에 두 sobel을 합칠 필요가 있다. gradient의 크기는 위의 L2 norm(Euclidean norm) 공식으로 나타낼 수 있다. (gradient의 공식은 3번에 있다. 각 편미분의 요소 제곱을 더한 후 root를 씌운다.) 계산을 줄이면서 L2 norm에 비슷한 값을 구하기 위하여 각 sobel 결과의 절댓값을 더할 수 있다.

 

결과 이미지들을 살펴본다.

 

방향성의 효과를 보기 위하여 배경의 기둥 부분을 살펴보자. original의 영상을 보면 수평 방향으로 pixel value의 변화가 심할 것이다. 따라서 horizontal 방향으로 계산한 Sobel_X의 경우 영상의 변화를 볼 수 있지만, Sobel_Y에서는 변화를 찾아볼 수 없다.

 

위와 비슷하게 코 부분도 X축 방향으로 pixel의 변화가 심할 것이다. 입술 같은 경우에는 vertical 방향으로 pixel의 변화를 예상할 수 있는데, 따라서 Sobel_X에 비해 Sobel_Y에서 더 많은 형체가 나타난 것을 볼 수 있다.  

 

Threshold 함수를 사용하면 특정 threshold를 기준으로 0과 1로 나눈 영상(Binary map)을 얻을 수 있다. 

 

다른 kernel들의 종류이다.

 

9번에서 얻었던 binary map을 살펴보면 배경에도 점처럼 부분이 형성된 것을 볼 수 있다. 이것은 high pass filter를 적용시키는 과정에서 noise와 detail이 증폭되어 나온 결과이다. 이것을 해결하기 위해 high pass filter를 거치기 전, low pass filter를 거쳐 원치 않은 신호들은 제거할 수 있다. 또한 Band pass filter를 적용하여 원하는 주파수 영역대의 성분들만 얻을 수 있을 것이다. (예로 기존 kernel의 format은 유지한 채, kernel size를 넓히고 gaussian 형태로 weight가 center에서 가장 크고 점차 더 낮아지는 형태로 구성한다면 효과는 band pass filter처럼 나타날 것이다.)

 

#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>

using namespace std;
using namespace cv;

int main() {
	Mat original = imread("lena.tif", IMREAD_GRAYSCALE);
	Mat sobel_X, sobel_Y;
	Mat sobel;
	Mat scharr_X, scharr_Y;
	Mat scharr;
	Mat sobelThresholded;
	
	// apply low pass filter (optional)
	GaussianBlur(original, original, Size(3,3), 1.5);

	/*
	void Sobel( InputArray src, OutputArray dst, int ddepth,
                         int dx, int dy, int ksize = 3,
                         double scale = 1, double delta = 0,
                         int borderType = BORDER_DEFAULT );
	*/
	Sobel(original, sobel_X, CV_8UC1, 1, 0, 3, 0.4, 128);	
	Sobel(original, sobel_Y, CV_8UC1, 0, 1, 3, 0.4, 128);
	sobel = abs(sobel_X) + abs(sobel_Y);
	
	/*
	double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type );
	*/
	threshold(sobel, sobelThresholded, 240, 255, cv::THRESH_BINARY);

	imwrite("grayScale.bmp", original);
	imwrite("sobel_X.bmp", sobel_X);
	imwrite("sobel_Y.bmp", sobel_Y);
	imwrite("sobel.bmp", sobel);
	imwrite("sobelThresholded.bmp", sobelThresholded);
}

'영상처리 > OpenCV' 카테고리의 다른 글

12. histogram introduction  (0) 2019.05.12
11. Laplacian  (0) 2019.05.02
09. Median filter  (2) 2019.04.24
08. Downsampling  (4) 2019.04.22
07. mean / gaussian filter  (1) 2019.04.18
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
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
글 보관함