개발/OpenCV

Edge Detection 코드/결과

njsung 2018. 4. 16. 21:37
반응형

안녕하세요 여러분

이번 포스팅에서는 저번 포스팅에서 작성했던

윤곽선 검출에 대한 실제 작동 코드와 결과를 보도록 하겠습니다.


윤곽선 검출의 이론에 대해 읽고 싶으시다면

아래 링크에서 읽어보세요!


2018/04/11 - [OpenCV] - Edge Detection의 방법 소개


1. 로버츠 마스크(Roberts Mask)



void RobertsEdgeDetect(const Mat& image, Mat& result, uchar thresh){

	// 수직마스크
	Mat maskX = (Mat_(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 0);
	// 수평마스크
	Mat maskY = (Mat_(3, 3) << 0, 0, -1, 0, 1, 0, 0, 0, 0);

	int filterOffset = 3 / 2;

	// Mat 초기화
	result = Mat::zeros(image.rows - filterOffset * 2, image.cols - filterOffset * 2, image.type());

	double sumEdgeX;
	double sumEdgeY;
	double magnitude;

	for (int yimage = filterOffset; yimage < image.rows - filterOffset; ++yimage){
		for (int ximage = filterOffset; ximage < image.cols - filterOffset; ++ximage){

			sumEdgeX = 0;
			sumEdgeY = 0;

			for (int ymask = -filterOffset; ymask <= filterOffset; ++ymask){
				for (int xmask = -filterOffset; xmask <= filterOffset; ++xmask){
					// 영상에 마스크를 연산하는 부분
					// sumEdgeX : 수직마스크적용, sumEdgeY : 수평마스크적용
					sumEdgeX += image.at(yimage + ymask, ximage + xmask) * maskX.at(filterOffset + ymask, filterOffset + xmask);
					sumEdgeY += image.at(yimage + ymask, ximage + xmask) * maskY.at(filterOffset + ymask, filterOffset + xmask);
				}
			}
			magnitude = sqrt(pow(sumEdgeY, 2) + pow(sumEdgeX, 2));
			//threshold 적용
			result.at(yimage - filterOffset, ximage - filterOffset) = ((magnitude > thresh) ? 0 : 255);
		}
	}
}





2. 프레윗 마스크(Prewitt Mask)



void PrewittEdgeDetect(const Mat& image, Mat& result, uchar thresh){

	// 수직마스크
	Mat maskX = (Mat_(3, 3) << 1, 0, -1, 1, 0, -1, 1, 0, -1);
	// 수평마스크
	Mat maskY = (Mat_(3, 3) << 1, 1, 1, 0, 0, 0, -1, -1, -1);

	int filterOffset = 3 / 2;

	// Mat 초기화


	result = Mat::zeros(image.rows - filterOffset * 2, image.cols - filterOffset * 2, image.type());

	double sumEdgeX;
	double sumEdgeY;
	double magnitude;

	for (int yimage = filterOffset; yimage < image.rows - filterOffset; ++yimage){
		for (int ximage = filterOffset; ximage < image.cols - filterOffset; ++ximage){

			sumEdgeX = 0;
			sumEdgeY = 0;

			for (int ymask = -filterOffset; ymask <= filterOffset; ++ymask){
				for (int xmask = -filterOffset; xmask <= filterOffset; ++xmask){
					// 영상에 마스크를 연산하는 부분
					// sumEdgeX : 수직마스크적용, sumEdgeY : 수평마스크적용
					sumEdgeX += image.at(yimage + ymask, ximage + xmask) * maskX.at(filterOffset + ymask, filterOffset + xmask);
					sumEdgeY += image.at(yimage + ymask, ximage + xmask) * maskY.at(filterOffset + ymask, filterOffset + xmask);
				}
			}
			magnitude = sqrt(pow(sumEdgeY, 2) + pow(sumEdgeX, 2));
			//threshold 적용
			result.at(yimage - filterOffset, ximage - filterOffset) = ((magnitude > thresh) ? 0 : 255);
		}
	}
}




3. 소벨 마스크(Sobel Mask)



void SobelEdgeDetect(const Mat& image, Mat& result, uchar thresh){

	// 수직마스크
	Mat maskX = (Mat_(3, 3) << 1, 0, -1, 2, 0, -2, 1, 0, -1);
	// 수평마스크
	Mat maskY = (Mat_(3, 3) << 1, 2, 1, 0, 0, 0, -1, -2, -1);

	int filterOffset = 3 / 2;

	// Mat 초기화
	result = Mat::zeros(image.rows - filterOffset * 2, image.cols - filterOffset * 2, image.type());

	double sumEdgeX;
	double sumEdgeY;
	double magnitude;

	for (int yimage = filterOffset; yimage < image.rows - filterOffset; ++yimage){
		for (int ximage = filterOffset; ximage < image.cols - filterOffset; ++ximage){

			sumEdgeX = 0;
			sumEdgeY = 0;

			for (int ymask = -filterOffset; ymask <= filterOffset; ++ymask){
				for (int xmask = -filterOffset; xmask <= filterOffset; ++xmask){
					// 영상에 마스크를 연산하는 부분
					// sumEdgeX : 수직마스크적용, sumEdgeY : 수평마스크적용
					sumEdgeX += image.at(yimage + ymask, ximage + xmask) * maskX.at(filterOffset + ymask, filterOffset + xmask);
					sumEdgeY += image.at(yimage + ymask, ximage + xmask) * maskY.at(filterOffset + ymask, filterOffset + xmask);
				}
			}
			magnitude = sqrt(pow(sumEdgeY, 2) + pow(sumEdgeX, 2));
			//threshold 적용
			result.at(yimage - filterOffset, ximage - filterOffset) = ((magnitude > thresh) ? 0 : 255);
		}
	}
}


4. 라플라시안 마스크(Laplacian Mask)



void LaplacianEdgeDetect(const Mat& image, Mat& result, uchar thresh,int type){

	Mat maskX, maskY;
	if (type == 4)
	{
		// 수직마스크
		maskX = (Mat_(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
		// 수평마스크
		maskY = (Mat_(3, 3) << 0, 1, 0, 1, -4, 1, 0, 1, 0);
	}
	else
	{
		// 수직마스크
		maskX = (Mat_(3, 3) << -1, -1, -1, -1, 8, -1, -1, -1, -1);
		// 수평마스크
		maskY = (Mat_(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1);
	}

	int filterOffset = 3 / 2;

	// Mat 초기화
	result = Mat::zeros(image.rows - filterOffset * 2, image.cols - filterOffset * 2, image.type());

	double sumEdgeX;
	double sumEdgeY;
	double magnitude;

	for (int yimage = filterOffset; yimage < image.rows - filterOffset; ++yimage){
		for (int ximage = filterOffset; ximage < image.cols - filterOffset; ++ximage){

			sumEdgeX = 0;
			sumEdgeY = 0;

			for (int ymask = -filterOffset; ymask <= filterOffset; ++ymask){
				for (int xmask = -filterOffset; xmask <= filterOffset; ++xmask){
					// 영상에 마스크를 연산하는 부분
					// sumEdgeX : 수직마스크적용, sumEdgeY : 수평마스크적용
					sumEdgeX += image.at(yimage + ymask, ximage + xmask) * maskX.at(filterOffset + ymask, filterOffset + xmask);
					sumEdgeY += image.at(yimage + ymask, ximage + xmask) * maskY.at(filterOffset + ymask, filterOffset + xmask);
				}
			}
			magnitude = sqrt(pow(sumEdgeY, 2) + pow(sumEdgeX, 2));
			//threshold 적용
			result.at(yimage - filterOffset, ximage - filterOffset) = ((magnitude > thresh) ? 0 : 255);
		}
	}
}



5. 캐니 엣지(Canny Edge)



Mat inputImg = imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat CannyImg;
Canny(inputImg, CannyImg, 50, 200,3);
imshow("Canny", CannyImg);



각 함수는 메인함수에서 호출할 수 있고

윤곽선을 찾아 저장할 Mat 타입의 변수를 지정해주면 됩니다!


3번째 인자는 threshold 값으로 50~70사이에서 변경 하시면

윤곽선 검출 결과가 달라지는걸 볼 수 있습니다!


이상 마치도록 하겠습니다!


감사합니다!




반응형