1. 에지검출과 영상의 미분
엣지란
- 영상에서 픽셀의 밝기 값이 급격하게 변하는 부분
- 일반적으로 배경과 객체, 또는 객체와 객체의 경계
기본적인 에지 검출방법
- 영상을 (x,y) 변수의 함수로 간주했을 때, 이 함수의 1차 미분값이 크게 나타나는 부분을 검출
- 입력영상에 가우시안 블러를 적용하여 잡음을 제거한 후 에지를 검출하는 것이 바람직함
1차미분의 근사화
다양한 에지검출 마스크
실습코드
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
void sobel_impl();
int main()
{
sobel_impl();
}
void sobel_impl()
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return;
}
Mat dx = Mat::zeros(src.size(), CV_8UC1);
Mat dy = Mat::zeros(src.size(), CV_8UC1);
Mat mag = Mat::zeros(src.size(), CV_8UC1);
for (int j = 1; j < src.rows - 1; j++) {
for (int i = 1; i < src.cols - 1; i++) {
int v1 = src.at<uchar>(j - 1, i + 1)
+ src.at<uchar>(j, i + 1) * 2
+ src.at<uchar>(j + 1, i + 1)
- src.at<uchar>(j - 1, i - 1)
- src.at<uchar>(j, i - 1) * 2
- src.at<uchar>(j + 1, i - 1);
int v2 = src.at<uchar>(j + 1, i + 1)
+ src.at<uchar>(j + 1, i) * 2
+ src.at<uchar>(j + 1, i + 1)
- src.at<uchar>(j - 1, i + 1)
- src.at<uchar>(j - 1, i) * 2
- src.at<uchar>(j - 1, i + 1);
dx.at<uchar>(j, i) = saturate_cast<uchar>(v1 + 128);
dy.at<uchar>(j, i) = saturate_cast<uchar>(v2 + 128);
mag.at<uchar>(j, i) = saturate_cast<uchar>(sqrt(v1 * v1 + v2 * v2));
}
}
Mat edge = mag > 120;
imshow("src", src);
imshow("dx", dx);
imshow("dy", dy);
imshow("mag", mag);
imshow("edge", edge);
waitKey();
destroyAllWindows();
}
결과영상
2. 그래디언트와 소벨필터
영상의 그래디언트
- 함수 f(x,y)를 x축과 y축으로 각각 편미분하여 벡터 형태로 표현한 것
- 그래디언트 크기: 픽셀 값의 차이 정도, 변화량
- 그래디언트 방향: 픽셀 값이 가장 급격하게 증가하는 방향
magnitude image(그래디언트 크기로 계산)
OpenCV sobel filter
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);
- src: 입력영상
- dst: 출력영상. src와 같은 크기, 같은 채널 수
- ddepth: 출력 영상 깊이
- dx, dy: x방향과 y방향으로의 미분 차수
- ksize: 커널 크기
- scale: 연산 결과에 추가적으로 곱할 값
- delta: 연산결과에 추가적으로 더할 값
- borderType: 가장자리 픽셀 확장 방식
OpenCV 2D 벡터의 크기 계산 함수
void magnitude(InputArray x, InputArray y, OutputArray magnitude);
- x: 2D벡터의 x좌표 행렬. 실수형.
- y: 2D벡터의 y좌표 행렬. x와 같은 크기. 실수형.
- magnitude: 2D 벡터의 크기 행렬. x와 같은 크기, 같은 타입
OpenCV 2D 벡터의 방향 계산 함수
void phase(InputArray, x, InputArray y, OutputArray angle, bool angleInDegrees = false);
- x: 2D벡터의 x좌표 행렬. 실수형.
- y: 2D벡터의 y좌표 행렬. x와 같은 크기. 실수형.
- angle: 2D벡터의 크기행렬. x와 같은 크기, 같은 타입.
- angleInDegrees: true이면 각도 단위, false이면 radian 단위.
sobel 실습 코드
void sobel_func()
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return;
}
Mat dx, dy;
Sobel(src, dx, CV_32FC1, 1, 0);
Sobel(src, dy, CV_32FC1, 0, 1);
Mat mag;
magnitude(dx, dy, mag);
mag.convertTo(mag, CV_8UC1);
Mat edge = mag > 150;
imshow("src", src);
imshow("mag", mag);
imshow("edge", edge);
waitKey();
destroyAllWindows();
}
결과영상