企业网站建设怎么样做会计分录,东莞房价下跌最惨一览表,flash属于网页制作平台吗,苏州专业做网站的公司OpenCV学习笔记#xff08;十二#xff09;#xff1a;边缘检测#xff1a;Canny(),Sobel(),Laplace(),Scharr滤波器
1#xff09;滤波#xff1a;边缘检测的算法主要是基于图像强度的一阶和二阶导数#xff0c;但导数通常对噪声很敏感#xff0c;因此必须采用滤波器来…OpenCV学习笔记十二边缘检测Canny(),Sobel(),Laplace(),Scharr滤波器
1滤波边缘检测的算法主要是基于图像强度的一阶和二阶导数但导数通常对噪声很敏感因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。常见的滤波方法主要有高斯滤波即采用离散化的高斯函数产生一组归一化的高斯核然后基于高斯核函数对图像灰度矩阵的每一点进行加权求和。 2增强增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。在具体编程实现时可通过计算梯度幅值来确定。 3检测经过增强的图像往往邻域中有很多点的梯度值比较大而在特定的应用中这些点并不是我们要找的边缘点所以应该采用某种方法来对这些点进行取舍。实际工程中常用的方法是通过阈值化方法来检测。
1、Canny()算子
Canny边缘检测算子是一个多级边缘检测算法
C: void Canny(InputArray image, //输入图像即源图像
OutputArray edges, // 输出的边缘图
double threshold1, // 第一个滞后性阈值
double threshold2, // 第二个滞后性阈值// 这个函数阈值1和阈值2两者的小者用于边缘连接而大者用来控制强边缘的初始段推荐的高低阈值比在2:1到3:1之间。
int apertureSize3, // 表示应用Sobel算子的孔径大小
bool L2gradientfalse // 一个计算图像梯度幅值的标识
)2、Sobel()算子
Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。它Sobel算子结合了高斯平滑和微分求导用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子将会产生对应的梯度矢量或是其法矢量。
void Sobel (
InputArray src, // 输入图
OutputArray dst, // 输出图
int ddepth, // 输出图像的深度// 若src.depth() CV_8U, 取ddepth -1/CV_16S/CV_32F/CV_64F// 若src.depth() CV_16U/CV_16S, 取ddepth -1/CV_32F/CV_64F// 若src.depth() CV_32F, 取ddepth -1/CV_32F/CV_64F// 若src.depth() CV_64F, 取ddepth -1/CV_64F
int dx, // x 方向上的差分阶数
int dy, // y 方向上的差分阶数
int ksize3, // 表示Sobel核的大小;必须取135或7
double scale1, // 计算导数值时可选的缩放因子
double delta0, // 表示在结果存入目标图之前可选的delta值
int borderTypeBORDER_DEFAULT // 边界模式
);3、Laplace()算子
Laplacian 算子是n维欧几里德空间中的一个二阶微分算子定义为梯度grad的散度div。Laplacian( )函数其实主要是利用sobel算子的运算。它通过加上sobel算子运算出的图像x方向和y方向上的导数来得到我们载入图像的拉普拉斯变换结果。
void Laplacian(InputArray src, // 源图像
OutputArray dst, // 输出的边缘图
int ddepth, // 输出图像的深度
int ksize1, // 用于计算二阶导数的滤波器的孔径尺寸
double scale1, // 计算拉普拉斯值的时候可选的比例因子
double delta0, // 表示在结果存入目标图之前可选的delta值
intborderTypeBORDER_DEFAULT // 边界模式
);4、scharr滤波器
scharr一般我就直接称它为滤波器而不是算子,主要是配合Sobel算子的运算而存在的。 scharr算子与Sobel的不同点是在平滑部分这里所用的平滑算子是1/16∗[3,10,3]相比于1/4∗[1,2,1]中心元素占的权重更重这可能是相对于图像这种随机性较强的信号邻域相关性不大所以邻域平滑应该使用相对较小的标准差的高斯函数也就是更瘦高的模板。
void Scharr(
InputArray src, // 源图OutputArray dst, // 目标图int ddepth, // 图像深度int dx, // x方向上的差分阶数int dy, //y方向上的差分阶数double scale1, //缩放因子double delta0, // delta值intborderTypeBORDER_DEFAULT // 边界模式)
4、代码示例
#include opencv2/opencv.hppusing namespace cv;
using namespace std;//原图原图的灰度版目标图
Mat g_srcImage, g_srcGrayImage,g_dstImage;//Canny边缘检测相关变量
Mat g_cannyDetectedEdges;
int g_cannyLowThreshold1;//TrackBar位置参数 //Sobel边缘检测相关变量
Mat g_sobelGradient_X, g_sobelGradient_Y;
Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y;
int g_sobelKernelSize1;//TrackBar位置参数 //Scharr滤波器相关变量
Mat g_scharrGradient_X, g_scharrGradient_Y;
Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y;int main()
{//载入原图g_srcImage imread(F:/C/2. OPENCV 3.1.0/7.1 edge detection 边缘检测/5.jpg);if( !g_srcImage.data ) { printf(Ohno读取srcImage错误~ \n); return false; }//显示原始图namedWindow(【原始图】);imshow(【原始图】, g_srcImage);// 1、创建与src同类型和大小的矩阵(dst)g_dstImage.create( g_srcImage.size(), g_srcImage.type() );// 2、将原图像转换为灰度图像cvtColor( g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY );// 3、创建trackbarnamedWindow( 【效果图】Canny边缘检测, WINDOW_AUTOSIZE );namedWindow( 【效果图】Sobel边缘检测, WINDOW_AUTOSIZE );createTrackbar( 参数值, 【效果图】Canny边缘检测, g_cannyLowThreshold, 120, on_Canny);createTrackbar( 参数值, 【效果图】Sobel边缘检测, g_sobelKernelSize, 3, on_Sobel);// 4、调用回调函数on_Canny(0, 0);on_Sobel(0, 0);// 5、调用封装了Scharr边缘检测代码的函数Scharr( );//轮询获取按键信息若按下Q程序退出while((char(waitKey(1)) ! q)) {}
}1Canny边缘检测窗口滚动条的回调函数
void on_Canny(int, void*)
{// 先使用 3x3内核来降噪blur( g_srcGrayImage, g_cannyDetectedEdges, Size(3,3) );// 运行我们的Canny算子// threshold1滞后性阈值1较小值用于边缘连接较大值控制强边缘的初始段// threshold2滞后性阈值2// apertureSize sobel算子的孔径大小Canny( g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold*3, 3 );//先将g_dstImage内的所有元素设置为0g_dstImage Scalar::all(0);//使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码来将原图g_srcImage拷到目标图g_dstImage中g_srcImage.copyTo( g_dstImage, g_cannyDetectedEdges);//显示效果图imshow( 【效果图】Canny边缘检测, g_dstImage );
}2Sobel边缘检测窗口滚动条的回调函数
void on_Sobel(int, void*)
{//Sobel算子是一阶导数的边缘检测算子在算法实现过程中通过3×3模板作为核与图像中的每个像素点做卷积和运算然后选取合适的阈值以提取边缘。//Sobel算子算法的优点是计算简单速度快。但是由于只采用了2个方向的模板只能检测水平和垂直方向的边缘//因此这种算法对于纹理较为复杂的图像其边缘检测效果就不是很理想。该算法认为//凡灰度新值大于或等于阈值的像素点时都是边缘点。//这种判断欠合理会造成边缘点的误判因为许多噪声点的灰度值也很大。// ddepth:输出图像的深度// dx,dy: x y方向上的差分阶数// scale 计算导数时的缩放因子// 求 X方向梯度Sobel( g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize1), 1, 1, BORDER_DEFAULT );// 对于输入数组的每个元素convertScaleAbs函数依次执行三个操作:缩放、取绝对值、转换为无符号8位类型 :// dst(I)saturate\_castuchar(|src(I)∗alphabeta|)convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X );
// Mat grad_xROI(grad_x,Rect(0,0,20,20));
// coutMendlgrad_xROIendl;
// imshow(【效果图】 X方向Sobel1, grad_x);// 求Y方向梯度Sobel( g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2*g_sobelKernelSize1), 1, 1, BORDER_DEFAULT );convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y );// 合并梯度addWeighted( g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage );//显示效果图imshow(【效果图】Sobel边缘检测, g_dstImage);}3Scharr边缘检测相关代码的函数
void Scharr( )
{// scharr算子与Sobel的不同点是在平滑部分这里所用的平滑算子是1/16∗[3,10,3]// 相比于1/4∗[1,2,1]中心元素占的权重更重这可能是相对于图像这种随机性较强的信号// 邻域相关性不大所以邻域平滑应该使用相对较小的标准差的高斯函数也就是更瘦高的模板。// 求 X方向梯度Scharr( g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT );convertScaleAbs( g_scharrGradient_X, g_scharrAbsGradient_X );//计算绝对值并将结果转换成8位// 求Y方向梯度Scharr( g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT );convertScaleAbs( g_scharrGradient_Y, g_scharrAbsGradient_Y );//计算绝对值并将结果转换成8位// 合并梯度addWeighted( g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage );//显示效果图imshow(【效果图】Scharr滤波器, g_dstImage);
}结果