opencv Canny边缘检测(c++)

文章目录

    • 说明
    • Canny原理
    • Canny()
    • DEMO
    • 效果

说明

Canny 边缘检测算法是 John F. Canny 于1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的最优算法。

Canny原理

  1. 降噪
    由于边缘检测容易受到图像中噪声的影响,因此第一步是使用5x5高斯滤波器消除图像中的噪声。

  2. 计算梯度值和梯度方向
    通过点乘一个sobel或其它算子得到不同方向的梯度值 G x , G_x , Gx, G y G_y Gy
    综合梯度通过以下公式计算梯度值和梯度方向:
    E d g e _ G r a d i e n t    ( G ) = G x 2 + G y 2 A n g l e    ( θ ) = tan ⁡ − 1 ( G y G x ) Edge\_Gradient \; (G) = \sqrt{G_x^2 + G_y^2} \\ Angle \; (\theta) = \tan^{-1} \bigg(\frac{G_y}{G_x}\bigg) Edge_Gradient(G)=Gx2+Gy2 Angle(θ)=tan1(GxGy)

  3. 非极大值抑制
    在高斯滤波过程中,边缘有可能被放大了。这个步骤使用一个规则来过滤不是边缘的点,使边缘的宽度尽可能为1个像素点:如果一个像素点属于边缘,那么这个像素点在梯度方向上的梯度值是最大的。否则不是边缘,将灰度值设为0。

  4. 使用上下阀值来检测边缘
    该阶段确定哪些边缘全部是真正的边缘,哪些不是。为此,我们需要两个阈值minVal和maxVal。强度梯度大于maxVal的任何边缘必定是边缘,而小于minVal的那些边缘必定是非边缘,因此将其丢弃。介于这两个阈值之间的对象根据其连通性被分类为边缘或非边缘。如果将它们连接到“边缘”像素,则将它们视为边缘的一部分。否则,它们也将被丢弃。见下图:
    opencv Canny边缘检测(c++)_第1张图片
    边缘A在maxVal之上,因此被视为“确定边缘”。尽管边C低于maxVal,但它连接到边A,因此也被视为有效边,我们得到了完整的曲线。但是边缘B尽管在minVal之上并且与边缘C处于同一区域,但是它没有连接到任何“确保边缘”,因此被丢弃。因此,非常重要的一点是我们必须相应地选择minVal和maxVal以获得正确的结果。

Canny()

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


@param image // 8位输入图像。
@param边缘 //输出边缘图; 单通道8位图像,其大小与image相同。
@param threshold1 //下阈值minVal。
@param threshold2 //上阈值maxVal。
@param holeSize //Sobel运算符的范围大小。
@param L2gradient //一个标志,指示是否应使用更准确的 L 2 L_2 L2 norm = ( d I / d x ) 2 + ( d I / d y ) 2 =\sqrt{(dI/dx)^2 + (dI/dy)^2} =(dI/dx)2+(dI/dy)2 来计算图像梯度幅度(L2gradient = true),或者使用默认值 L 1 L_1 L1 norm = ∣ d I / d x ∣ + ∣ d I / d y ∣ =|dI/dx|+|dI/dy| =dI/dx+dI/dy就已经足够(L2gradient = false)。

DEMO

int main() {
	cv::namedWindow("src", 0);
	cv::namedWindow("dst", 0);
	cv::Mat src = cv::imread("./img/test1.jpg", 1);
	cv::Mat dst;
	//cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
	cv::Canny(src, dst, 100, 300);
	cv::imshow("src", src);
	cv::imshow("dst", dst);
	cv::waitKey(0);
	cv::imwrite("./img/dst.jpg", dst);
	cv::imwrite("./img/src.jpg", src);
}

效果

原图:
opencv Canny边缘检测(c++)_第2张图片

结果:
opencv Canny边缘检测(c++)_第3张图片

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