Bootstrap

opencv学习笔记21-opencv边缘提取(canny算子)

一、函数

a.Sobel函数:

(1)函数原型:

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 );

(2)函数作用:

计算图像的一阶、二阶、三阶或混合导数,使用扩展的Sobel算子。

(3)参数说明:

  • InputArray src:输入图像。
  • OutputArray dst:输出图像,其大小和通道数与输入图像src相同。
  • int ddepth:输出图像的深度,可以查看OpenCV文档了解不同的深度组合。对于8位输入图像,导数可能会被截断。
  • int dx:x方向上的导数阶数。
  • int dy:y方向上的导数阶数。
  • int ksize:扩展Sobel核的大小;必须是1、3、5或7。当ksize = 1时,使用3x1或1x3核,不进行高斯平滑。ksize = FILTER_SCHARR (-1)是一个特殊值,对应于3x3 Scharr滤波器,可能比3x3 Sobel滤波器给出更准确的结果。
  • double scale:可选的比例因子,用于计算得到的导数值;默认情况下,不应用缩放(见getDerivKernels函数的详细信息)。
  • double delta:可选的delta值,在将结果存储到dst之前加到结果上。
  • int borderType:像素外推方法,见BorderTypes。不支持BORDER_WRAP

(4) 补充说明:

  Sobel函数通过将图像与适当的核卷积来计算图像导数。Sobel算子结合了高斯平滑和微分,因此结果对噪声有一定的抵抗力。通常,这个函数被调用时参数设置为(dx = 1, dy = 0, ksize = 3)或(dx = 0, dy = 1, ksize = 3),以计算图像的一阶x或y导数。

b.Canny函数:

(1) 函数原型:

CV_EXPORTS_W void Canny( InputArray image, OutputArray edges, double threshold1, 
            double threshold2, int apertureSize = 3, bool L2gradient = false );

(2) 函数作用:

用于使用Canny边缘检测算法在图像中检测边缘。

(3)参数说明:

  • InputArray image:函数的第一个参数,表示输入的8位图像,用于边缘检测。
  • OutputArray edges:函数的第二个参数,表示输出的边缘图,也是一个8位单通道图像,其大小与输入图像相同。
  • double threshold1 和 double threshold2:这两个参数是Canny算法中的阈值,用于边缘连接和检测强边缘的初始段。
  • int apertureSize:Sobel算子的孔径大小,默认值为3。
  • bool L2gradient:一个标志,指示是否使用更准确的L2范数计算图像梯度的幅度(L2gradient=true),或者使用默认的L1范数(L2gradient=false)。

(4) 补充说明:

Canny算法是一种流行的边缘检测方法,由John F. Canny在1986年提出。canny函数的作用是接受一个输入图像,通过Canny算法检测图像中的边缘,并将检测到的边缘标记在输出的边缘图上。这个函数在图像处理和计算机视觉领域中非常有用,特别是在需要边缘信息进行进一步分析或处理的任务中。

c. Canny函数(重载版本):

(1)函数原型:

CV_EXPORTS_W void Canny( InputArray dx, InputArray dy, OutputArray edges,
         double threshold1, double threshold2, bool L2gradient = false );

(2)函数作用:

这个版本允许用户使用自定义的图像梯度来检测边缘。 

(3)参数说明:

  • nputArray dx:函数的第一个参数,表示输入图像的x方向导数(即水平方向的梯度),数据类型为16位有符号短整型(CV_16SC1或CV_16SC3)。
  • InputArray dy:函数的第二个参数,表示输入图像的y方向导数(即垂直方向的梯度),数据类型与dx相同。
  • OutputArray edges:函数的第三个参数,表示输出的边缘图,是一个8位单通道图像,其大小与输入图像相同。
  • double threshold1 和 double threshold2:这两个参数与之前相同,是Canny算法中的阈值。
  • bool L2gradient:这个参数也与之前相同,用于指示是否使用L2范数或L1范数来计算图像梯度的幅度。

 (4)补充说明:

这个重载版本的Canny函数允许用户在已知图像梯度的情况下进行边缘检测,这在某些情况下可以提高算法的效率或准确性。例如,如果用户已经计算了图像的梯度,那么他们可以使用这个版本的函数来避免重复计算。

二、示例代码:

#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>           
#include <opencv2/videoio.hpp>       
#include <opencv2/objdetect.hpp>        
#include <opencv2/highgui/highgui_c.h>  
#include <iostream>                     

using namespace cv;                    
using namespace std;      

int main()
{
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
	Mat canny_image = imread("C:\\Users\\86173\\Desktop\\TI\\canny.jpg");
	//判断图片是否打开
	if (canny_image.empty())
	{
		cout << "Can't open picture" << endl;
		return 0;
	}
	//定义图片容器
	Mat image_dx;
	Mat image_dy;
	Mat image_canny1;
	Mat image_canny2;
	Mat scr_image;

		Sobel(canny_image, image_dx, CV_16S, 1, 0, 3);//x方向上的梯度
		Sobel(canny_image, image_dy, CV_16S, 0, 1, 3);//y方向上的梯度
		Canny(image_dx, image_dy, image_canny1, 20, 60);


		//转化为灰度图,在进行边缘提取
		cvtColor(canny_image, scr_image, COLOR_BGR2GRAY);
		Canny(scr_image, image_canny2, 20, 60);

		imshow("image_canny1", image_canny1);
		imshow("image_canny2", image_canny2);
	
		waitKey(0);
		destroyAllWindows();
		return 0;
}

三、运行结果:

;