若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105402418
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
上一篇:《OpenCV开发笔记(三十九):红胖子8分钟带你深入了解sobel算子边缘检测(图文并茂+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(四十一):红胖子8分钟带你深入了解scharr滤波器算子边缘检测(图文并茂+浅显易懂+程序源码)》
红胖子来也!!!
本篇章讲解Laplacian拉普拉斯算子边缘检测。
Demo图像结果位置示意图:
.
拉普拉斯算子是n维欧几里德空间中的一个二阶微分子,定义为梯度grad的㪚度div。如果f是二阶可微的实函数,则f的拉普拉斯算子定义为:
f的拉普拉斯算子也是笛卡儿坐标系中的所有非混合二阶偏导数求和:
作为一个二阶微分算子,拉普拉斯算子把C函数映射到C函数,对于k≥2。表达式(1)(或(2))定义了一个算子Δ : C(R) → C(R),或更一般地,定义了一个算子Δ : C(Ω) → C(Ω),对于任何开集Ω。
对于阶跃状边缘,导数在边缘点出现零交叉,即边缘点两旁二阶导数取异号。据此,对数字图像{f(i,j)}的每个像素,取它关于x轴方向和y轴方向的二阶差分之和,表示为
Laplacce算子是一种各向同性算子,二阶微分算子,在只关心边缘的位置而不考虑其周围的象素灰度差值时比较合适。
Laplace算子对孤立象素的响应要比对边缘或线的响应要更强烈,因此只适用于无噪声图象。存在噪声情况下,使用Laplacian算子检测边缘之前需要先进行低通滤波。所以,通常的分割算法都是把Laplacian算子和平滑算子结合起来生成一个新的模板。
由于 Laplacian使用了图像梯度,它内部的代码其实是调用了 Sobel 算子的。
让一幅图像减去它的Laplacian可以增强对比度。
void Laplacian( InputArray src,
OutputArray dst,
int ddepth,
int ksize = 1,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT );
void OpenCVManager::testLaplacian()
{
QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/7.jpg";
cv::Mat srcMat = cv::imread(fileName1.toStdString());
if(!srcMat.data)
{
qDebug() << __FILE__ << __LINE__
<< "Failed to load image:" << fileName1;
return;
}
int width = 300;
int height = 200;
cv::resize(srcMat, srcMat, cv::Size(width, height));
cv::String windowName = _windowTitle.toStdString();
cvui::init(windowName);
cv::Mat dstMat;
dstMat = cv::Mat::zeros(srcMat.size(), srcMat.type());
cv::Mat windowMat = cv::Mat(cv::Size(dstMat.cols * 3, dstMat.rows * 3),
srcMat.type());
int ksize = 1; // 核心大小
int sigmaX = 0; // x方向的标准偏差
int sigmaY = 0; // y方向的标准偏差
int ksize2 = 0;
int sigmaS = 160;
int sigmaR = 2;
cvui::window(windowMat, dstMat.cols, 0, dstMat.cols, dstMat.rows, "settings");
cv::Mat grayMat;
cv::Mat grayMat3Channels;
cv::Mat mat;
cv::cvtColor(srcMat, grayMat, CV_BGR2GRAY);
cv::cvtColor(grayMat, grayMat3Channels, CV_GRAY2BGR);
while(true)
{
windowMat = cv::Scalar(0, 0, 0);
// 原图先copy到左边
cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
cv::Range(0, srcMat.cols));
cv::addWeighted(leftMat, 1.0f, srcMat, 1.0f, 0.0f, leftMat);
// 中间为调整滤波参数的相关设置
cvui::printf(windowMat, 375, 20, "ksize = size * 2 + 1");
cvui::trackbar(windowMat, 375, 30, 165, &ksize, 0, 10);
cvui::printf(windowMat, 375, 80, "sigmaX");
cvui::trackbar(windowMat, 375, 90, 165, &sigmaX, 0, 100);
cvui::printf(windowMat, 375, 140, "sigmaY");
cvui::trackbar(windowMat, 375, 150, 165, &sigmaY, 0, 100);
// 复制灰度图像
{
cv::Mat rightMat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(rightMat, 0.0f, grayMat3Channels, 1.0f, 0.0f, rightMat);
}
{
// 高斯滤波
cv::Mat mat;
cv::GaussianBlur(grayMat3Channels, mat, cv::Size(ksize * 2 + 1, ksize * 2 + 1), sigmaX / 10.f, sigmaY / 10.f);
// 效果图copy到右边
// 注意:rang从位置1到位置2,不是位置1+宽度
cv::Mat rightMat = windowMat(cv::Range(0, srcMat.rows),
cv::Range(srcMat.cols * 2, srcMat.cols * 3));
cv::addWeighted(rightMat, 0.0f, mat, 1.0f, 0.0f, rightMat);
// 高斯滤波后进行边缘检测
// 使用边缘检测
cv::Laplacian(mat, dstMat, CV_8UC3, ksize2 * 2 + 1);
cv::Mat rightMat2 = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 2, srcMat.cols * 3));
cv::addWeighted(rightMat2, 0.0f, dstMat, 1.0f, 0.0f, rightMat2);
}
{
cvui::printf(windowMat,
srcMat.cols * 1 + 75,
srcMat.rows * 1 + 20,
"ksize = size * 2 + 1");
cvui::trackbar(windowMat,
srcMat.cols * 1 + 75,
srcMat.rows * 1 + 50,
165,
&ksize2,
0,
1);
// 使用边缘检测
cv::Laplacian(grayMat3Channels, dstMat, CV_8UC3, ksize2 * 2 + 1);
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
}
{
cvui::printf(windowMat, 75 + width * 1, height * 2 + 20, "sigmaS");
cvui::trackbar(windowMat, 75 + width * 1, height * 2 + 50, 165, &sigmaS, 101, 10000);
cvui::printf(windowMat, 75 + width * 1, height * 2 + 90, "sigmaR");
cvui::trackbar(windowMat, 75 + width * 1, height * 2 + 120, 165, &sigmaR, 1, 100);
// 使用自适应流形应用高维滤波。
cv::Mat tempMat;
cv::Ptr pAdaptiveManifoldFilter
= cv::ximgproc::createAMFilter(sigmaS/100.0f, sigmaR/100.0f, true);
pAdaptiveManifoldFilter->filter(grayMat, tempMat);
// 使用边缘检测
cv::cvtColor(tempMat, tempMat, CV_GRAY2BGR);
cv::Laplacian(tempMat, tempMat, CV_8UC3, ksize2 * 2 + 1);
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 2, srcMat.cols * 3));
cv::addWeighted(mat, 0.0f, tempMat, 1.0f, 0.0f, mat);
}
// 更新
cvui::update();
// 显示
cv::imshow(windowName, windowMat);
// esc键退出
if(cv::waitKey(25) == 27)
{
break;
}
}
}
对应版本号v1.35.0
上一篇:《OpenCV开发笔记(三十九):红胖子8分钟带你深入了解sobel算子边缘检测(图文并茂+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(四十一):红胖子8分钟带你深入了解scharr滤波器算子边缘检测(图文并茂+浅显易懂+程序源码)》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105402418