您的位置:首页 > 运维架构

Opencv学习笔记(二十三) 改进边缘检测算子-----Marr-Hildresh

2017-10-17 18:33 507 查看
Marr-Hildresh边缘检测算子,用于解决边缘检测的核心问题---定位精度和抑制噪声。Marr-Hildreth算子以高斯函数为平滑算子,结合拉普拉斯算子提取二阶导数的零交叉理论进行边缘检测。边缘检测中灰度变化与图像尺寸无关,检测算子可为不同尺度,灰度变化梯度在一阶导数的极值点(波峰或波谷),或在二阶导数为零的交叉点。

由于噪声点对边缘检测有一定的影响,所以效果更好的边缘检测器是LoG算子。它把高斯平滑滤波器和拉普拉斯锐化滤波器结合起来,先平滑掉噪声,再进行边缘检测,所以效果会更好。

Marr-Hildreth边缘检测代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void marrEdge(const Mat src, Mat& result, int kerValue, double delta)
{
//计算LoG算子
Mat kernel;
//半径
int kerLen = kerValue / 2;
kernel = Mat_<double>(kerValue, kerValue);
//滑窗
for (int i = -kerLen; i <= kerLen; i++)
{
for (int j = -kerLen; j <= kerLen; j++)
{
//生成核因子
kernel.at<double>(i + kerLen, j + kerLen) = exp(-((pow(j, 2) + pow(i, 2)) / (pow(delta, 2) * 2)))
*((pow(j, 2) + pow(i, 2) - 2 * pow(delta, 2)) / (2 * pow(delta, 4)));
}
}
//设置输入参数
int kerOffset = kerValue / 2;
Mat laplacian = (Mat_<double>(src.rows - kerOffset * 2, src.cols - kerOffset * 2));
result = Mat::zeros(src.rows - kerOffset * 2, src.cols - kerOffset * 2, src.type());
double sumLaplacian;
//遍历计算卷积图像的拉普拉斯算子
for (int i = kerOffset; i < src.rows - kerOffset; ++i)
{
for (int j = kerOffset; j < src.cols - kerOffset; ++j)
{
sumLaplacian = 0;
for (int k = -kerOffset; k <= kerOffset; ++k)
{
for (int m = -kerOffset; m <= kerOffset; ++m)
{
//计算图像卷积
sumLaplacian += src.at<uchar>(i + k, j + m)*kernel.at<double>(kerOffset + k, kerOffset + m);
}
}
//生成拉普拉斯结果
laplacian.at<double>(i - kerOffset, j - kerOffset) = sumLaplacian;
}
}
for (int y = 1; y < result.rows - 1; ++y)
{
for (int x = 1; x < result.cols-1; ++x)
{
result.at<uchar>(y, x) = 0;
//领域判定
if (laplacian.at<double>(y - 1, x)*laplacian.at<double>(y + 1, x) < 0)
{
result.at<uchar>(y, x) = 255;
}
if (laplacian.at<double>(y, x - 1)*laplacian.at<double>(y, x + 1) < 0)
{
result.at<uchar>(y, x) = 255;
}
if (laplacian.at<double>(y + 1, x - 1)*laplacian.at<double>(y - 1, x + 1) < 0)
{
result.at<uchar>(y, x) = 255;
}
if (laplacian.at<double>(y - 1, x - 1)*laplacian.at<double>(y + 1, x + 1) < 0)
{
result.at<uchar>(y, x) = 255;
}
}
}
}
int main()
{
Mat srcImage = imread("C:/Users/si/Desktop/2.png");
if (!srcImage.data)
return -1;
Mat edge,srcGray;
cvtColor(srcImage, srcGray, CV_RGB2GRAY);
marrEdge(srcGray, edge, 9, 1.6);
imshow("srcImage", srcImage);
imshow("edge", edge);
waitKey(0);
return 0;

}


程序运行效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: