개발/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사이에서 변경 하시면
윤곽선 검출 결과가 달라지는걸 볼 수 있습니다!
이상 마치도록 하겠습니다!
감사합니다!
반응형