c++ opencv4.5.5 学习笔记(六 )边缘检测(Sobel算子、Laplacian、Canny、LoG)

边缘检测

  • 1、边缘检测即图像差分
  • 2、常见边缘检测算子包括Robert算子, Sobel算子, LoG算子等, 其中Sobel算子最为常用, LoG 是先进行高斯滤波再进行Laplacian
  • 3、二维图像的边缘具有强度和方向两个性质
  • 4、Canny算子的基本优点在于检测准确、 对噪声稳健,在实际中广泛应用

Sobel算子边缘检测

//Sobel算子边缘检测
void photoSobel(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * Sobel		Sobel算子边缘检测器
	  * src			原始图
	  * dst			目标图
	  * ddepth		目标图像的所需深度,包括CV_16S/CV_32F/CV_64F等
	  * ksize		滤波器大小,通常可选为(5,5)或(3,3),或直接使用缺省
	  * 第四个参数,int类型dx,x 方向上的差分阶数。
      * 第五个参数,int类型dy,y方向上的差分阶数。
      * 第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
      * 第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
      * 第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
	  * 第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
	  **/
	CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
                         int dx, int dy, int ksize = 3,
                         double scale = 1, double delta = 0,
                         int borderType = BORDER_DEFAULT );
                         
	//求 X方向梯度
	cv::Mat grad_x, grad_y, abs_grad_x, abs_grad_y;
	cv::Sobel(src, grad_x, CV_16S, 1, 0);
	cv::convertScaleAbs(grad_x, grad_x);//使用线性变换转换输入数组元素成8位无符号整型
	

	//求 Y方向梯度
	cv::Sobel(src, grad_y, CV_16S, 0, 1);
	cv::convertScaleAbs(grad_y, grad_y);//使用线性变换转换输入数组元素成8位无符号整型
	//将图片转化成为8位图形进行显示

	//合并梯度(近似)
	cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
	
}

Laplacian边缘检测

//Laplacian边缘检测
void photoLaplacian(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * Laplacian	Laplacian边缘检测器
	  * src			原始图
	  * dst			目标图
	  * ddepth		目标图像的所需深度,包括CV_16S/CV_32F/CV_64F等
	  * ksize		滤波器大小,通常可选为(5,5)或(3,3),或直接使用缺省
	  **/
	CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth,
                             int ksize = 1, double scale = 1, double delta = 0,
                             int borderType = BORDER_DEFAULT );
	cv::Laplacian(src, dst, CV_16S);
	//将图片转化成为8位图形进行显示
	cv::convertScaleAbs(dst, dst);
}

Canny边缘检测

Canny算子核心优点:边缘可自动连通
算法步骤:

  1. 平滑图像
  2. 计算梯度(幅值和方向)
  3. 梯度幅值进行非极大值抑制
  4. 自动边缘连接
//Canny边缘检测
void photoCanny(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * Canny             Canny边缘检测器
	  * image             源图像,灰度
	  * detected_edges    检测器的输出(可以与输入相同)
	  * threshold1        阈值1
	  * threshold2        阈值2
	  * apertureSize      Sobel算子大小
	  * canny边缘检测算法:
		1.两个阈值是有区别的,高的那个阈值是将要提取轮廓的物体与背景区分开来,就像阈值分割的参数一样,高的阈值是决定目标与背景对比度的;低的阈值是用来平滑边缘的轮廓,有时高的阈值设置太大了,可能边缘轮廓不连续或者不够平滑,通过低阈值来平滑轮廓线,或者使不连续的部分连接起来。
		2.两个阈值:T1,T2。大于T1的称为强边界。T1和T2之间的为弱边界。
		如果只有强边界,那么边界可能断断续续。而且会少分割。所以弱边界的作用就是解决上面这个问题。如果强边界点的8连通区域内有弱边界点,那么认为该弱边界点为强边界。
	  **/
	CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false );
	cv::Canny(src, dst, 50, 150);
}

测试代码

/**
  * 边缘检测Demo
  * Sobel算子、Laplacian、Canny
  * 1、边缘检测即图像差分
  * 2、常见边缘检测算子包括Robert算子, Sobel算子, LoG算子等, 其中Sobel算子最为常用, LoG 是先进行高斯滤波再进行Laplacian
  * 3、二维图像的边缘具有强度和方向两个性质
  * 4、Canny算子的基本优点在于检测准确、 对噪声稳健,在实际中广泛应用
  **/

#include 
#include 


//Sobel算子边缘检测
//Sobel算子边缘检测
void photoSobel(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * Sobel		Sobel算子边缘检测器
	  * src			原始图
	  * dst			目标图
	  * ddepth		目标图像的所需深度,包括CV_16S/CV_32F/CV_64F等
	  * ksize		滤波器大小,通常可选为(5,5)或(3,3),或直接使用缺省
	  * 第四个参数,int类型dx,x 方向上的差分阶数。
      * 第五个参数,int类型dy,y方向上的差分阶数。
      * 第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
      * 第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
      * 第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
	  * 第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
	  **/
	//求 X方向梯度
	cv::Mat grad_x, grad_y, abs_grad_x, abs_grad_y;
	cv::Sobel(src, grad_x, CV_16S, 1, 0);
	cv::convertScaleAbs(grad_x, grad_x);//使用线性变换转换输入数组元素成8位无符号整型
	

	//求 Y方向梯度
	cv::Sobel(src, grad_y, CV_16S, 0, 1);
	cv::convertScaleAbs(grad_y, grad_y);//使用线性变换转换输入数组元素成8位无符号整型
	//将图片转化成为8位图形进行显示

	//合并梯度(近似)
	cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
	
}

//Laplacian边缘检测
void photoLaplacian(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * Laplacian	Laplacian边缘检测器
	  * src			原始图
	  * dst			目标图
	  * ddepth		目标图像的所需深度,包括CV_16S/CV_32F/CV_64F等
	  * ksize		滤波器大小,通常可选为(5,5)或(3,3),或直接使用缺省
	  **/
	cv::Laplacian(src, dst, CV_16S);
	//将图片转化成为8位图形进行显示
	cv::convertScaleAbs(dst, dst);
}

//Canny边缘检测
void photoCanny(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * Canny             Canny边缘检测器
	  * image             源图像,灰度
	  * detected_edges    检测器的输出(可以与输入相同)
	  * threshold1        阈值1
	  * threshold2        阈值2
	  * apertureSize      Sobel算子大小
	  **/
	cv::Canny(src, dst, 50, 150);

}

int main()
{
	// 读取图片
	std::string imagename = "Standard_image/lena.jpg";
	cv::Mat img = cv::imread(imagename, cv::IMREAD_GRAYSCALE);
	// 判断载入图片是否成功
	if (img.empty())
	{
		std::cout << "miss the image file : " + imagename << std::endl;
		return -1;
	}

	cv::Mat SobelImg, LaplacianImg, CannyImg;

	photoSobel(img, SobelImg);
	photoLaplacian(img, LaplacianImg);
	photoCanny(img, CannyImg);

	cv::imshow("原图", img);
	cv::imshow("Sobel", SobelImg);
	cv::imshow("Laplacian", LaplacianImg);
	cv::imshow("Canny", CannyImg);

	cv::waitKey();

	return 0;
}

测试结果

原图
c++ opencv4.5.5 学习笔记(六 )边缘检测(Sobel算子、Laplacian、Canny、LoG)_第1张图片
Sobel
c++ opencv4.5.5 学习笔记(六 )边缘检测(Sobel算子、Laplacian、Canny、LoG)_第2张图片
Laplacian
c++ opencv4.5.5 学习笔记(六 )边缘检测(Sobel算子、Laplacian、Canny、LoG)_第3张图片
Canny
c++ opencv4.5.5 学习笔记(六 )边缘检测(Sobel算子、Laplacian、Canny、LoG)_第4张图片

你可能感兴趣的:(opencv,学习笔记,opencv,计算机视觉,c++)