관심쟁이 영호

[#17] OpenCV (With. CPP) ㅣ 에지검출 ㅣ 1차 미분 마스크, 2차 미분 마스크, 캐니 에지 본문

카테고리 없음

[#17] OpenCV (With. CPP) ㅣ 에지검출 ㅣ 1차 미분 마스크, 2차 미분 마스크, 캐니 에지

관심쟁이 영호 2020. 11. 24. 01:30
반응형

안녕하세요!

관심쟁이 영호입니당.

 

오늘 공부할 과목은

OpenCV입니다!

 


1차 미분 마스크란?

 

미분을 이용하여 함수의 순간 변화율을 계산하여 에지를 검출하는데 사용되는 마스크입니다!

해당 마스크는

 

-1 0 1   1 -2 1
-2 0 2 0 0 0
-1 0 1 1 2 1
수직 마스크 수평 마스크

이렇게 나타 낼 수 있는데요!

이 것은 "소벨 마스크"를 뜻하여 가장 대표적인 마스크입니다!

그럼 코드로 살펴볼게요!

 

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

void differential(Mat image, Mat& dst, float data1[], float data2[]) {

	Mat dst1, mask1(3, 3, CV_32F, data1);
	Mat dst2, mask2(3, 3, CV_32F, data2);

	filter2D(image, dst1, CV_32F, mask1);
	filter2D(image, dst1, CV_32F, mask2);
	magnitude(dst1, dst2, dst);
	dst.convertTo(dst, CV_8U);

	convertScaleAbs(dst1, dst1);
	convertScaleAbs(dst2, dst2);

	imshow("dst1 - 수직 마스크", dst1);
	imshow("dst2 - 수직 마스크", dst2);
}



int main()
{
	Mat image = imread("../image/sample.jpg", IMREAD_GRAYSCALE);
	
	CV_Assert(image.data);

	float data1[] = {
		-1, 0, 1,
		-1, 0, 1,
		-1, 0, 1
	};

	float data2[] = {
		-1, -1, -1,
		0, 0, 0,
		1, 1, 1
	};

	Mat dst, dst3, dst4;
	differential(image, dst, data1, data2);

	Sobel(image, dst3, CV_32F, 1, 0, 3);
	Sobel(image, dst4, CV_32F, 0, 1, 3);
	convertScaleAbs(dst3, dst3);
	convertScaleAbs(dst4, dst4);
	imshow("image", image), imshow("", dst);
	imshow("dst3-수직_OpenCV", dst3), imshow("dst4-수평_OpenCV", dst4);

	
	waitKey(0);

		return 0;
}

 

순서는 앞서 차연산자의 방법과 똑같아요!

차분 연산에서는 for문을 여러번 돌려서 마스크 값을 행렬 번수에 담아서 했는데,

회선을 제공하는 함수인  filter2D를 사용하고,

회선한 후 값을 magnitude를 넣어주었습니다!

 

근데 책에서 나온 대로 코드를 작성했는데..

오류가 뜨네요 ㅠㅠ

사이즈 문제인것 같은데!

 

어쨋든 저런 흐름이니까 패스!

 

2차 미분 마스크

 

1차 미분 연산자는 밝기가 급격히 변화하는 영역이랑 점진적으로 변화하는 부분까지 민감하게 에지를 검출해서 많은 에지가 검출이 될 수 있어요!

그래서 1차미분을 통해서 에지를 검출한 다음 한번 더 미분을 통해서 에지를 검출하는 것이

2차 미분을 통한 에지 검출입니다! 2차 미분에는 라플라시안, Log/Dog검출이 있는데 라플라시안 에지 검출을 살펴볼게요!

 

코드를 바로 살펴보시죠.

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("../image/sample.jpg", IMREAD_GRAYSCALE);
	
	CV_Assert(image.data);

	short data1[] = {
		0, 1, 0,
		1, -4, 1,
		0, 1, 0
	};

	short data2[] = {
		-1, -1, -1,
		-1, 8, -1,
		-1, -1, -1
	};

	Mat dst1, dst2, dst3;
	Mat mask4(3, 3, CV_16S, data1);
	Mat mask8(3, 3, CV_16S, data2);

	filter2D(image, dst1, CV_16S, mask4);
	filter2D(image, dst2, CV_16S, mask8); //filter2D를 통하여 라플라시안 수행
	Laplacian(image, dst3, CV_16S, 1); //라플라시안 수행 함수
	
	convertScaleAbs(dst1, dst1);
	convertScaleAbs(dst2, dst2);
	convertScaleAbs(dst3, dst3);


	
	
	imshow("image", image), imshow("filter2D", dst1);
	imshow("filter2D-4방향", dst2), imshow("filter2D- 8방향", dst3);

	

	
	waitKey(0);

		return 0;
}

결과는 이렇게 나오네요!

openCV에서 제공해주는 라플라시안 함수를 이용한 방법과

filter2D함수를 이용한 방법 두 가지로 해보았어요!

 

라플라시안에 대한 공식이 있는데, 너무 복잡해요 ㅠ

그냥 함수 가따 쓰는걸로 해요 ㅋㅋㅋ

 

 

 


오늘은 여기까지 공부를 해보겠습니다!

 

이러

300x250
Comments