OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)

目录

一、基础理论

1、作用及介绍

1、原理

2、过程

3、Canny函数

二、回调函数及总代码

效果

参考资料


​​​​​​​

一、基础理论

1、作用及介绍

Canny边缘检测是非常流行的边缘检测算法,被认为是最优的边缘检测算法

1、原理

首先在x和y方向求一阶导数,然后组合为4个方向的导数,这些方向导数达到局部最大值的点就是组成边缘的候选点

优点:分别用两种不同的阈值检测强边缘弱边缘。(当且仅当强边缘与弱边缘相连时,才将若边缘输出到图像中)

2、过程

四步法:

第一步,图像降噪高斯滤波

第二步,计算图像梯度sobel算子,计算梯度大小方向

梯度方向总是与边缘垂直,梯度方向有四类:垂直、水平、两个对角线方向。

第三步,非极大值抑制(保留极大值)。利用梯度方向像素判断是否为边界点,去除非边界点。(边缘变“瘦”

OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)_第1张图片

第四步,双阈值筛选(保留极大值)。设置两个阈值,确定最终边界。

现在要确定真正的边界。我们设置两个阈值: minVal和 maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。(和极大值相连则保留)如下图:A和C视为边界,B不视为边界。
OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)_第2张图片

3、Canny函数

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

InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
double类型的threshold1,第一个滞后性阈值【低阈值】。值越大,找到的边缘越少
double类型的threshold2,第二个滞后性阈值【高阈值】。
int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。

C++:

Canny(src, dst, 100,        255,        3);          //Canny函数
    //          低阈值     高阈值       sobel算子孔径大小

 python:

dst = cv.Canny(img, 100,  255)
    #              低阈值 高阈值

Canny算子处理: 

C++:

//Canny边缘检测
void Canny()
{
    Canny(src, dst, 100,        255,            3);          //Canny函数
    //              低阈值     高阈值       sobel算子孔径大小
    imshow(window, dst);
}

 python:

# Canny最优微分算子
def Canny():
    dst = cv.Canny(img, 100,  255)
    #                   低阈值 高阈值
    cv.imshow("dst", dst)

 

OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)_第3张图片

二、回调函数及总代码

C++:

//Canny算子回调函数(参数可调)
#include   
#include   

using namespace cv;
using namespace std;

Mat src, dst, gray;
string window = "Canny";
int Min = 50, Max = 200;          //初始参数

void Callback_Canny_Min(int, void*);         //Canny算子回调函数
void Callback_Canny_Max(int, void*);

//图片初始化
void Image_Init()
{
    src = imread("Resource/test17.jpg");
    imshow("原图", src);
}

//Canny边缘检测
void Canny()
{
    Canny(src, dst, 100,        255,            3);          //Canny函数
    //              低阈值     高阈值       sobel算子孔径大小
    imshow(window, dst);
}

int main()
{
    Image_Init();                   //图片初始化

    //先第一次显示(Canny)
    Canny();

    //回调函数
    createTrackbar("min:", window, &Min, 255, Callback_Canny_Min);
    createTrackbar("max:", window, &Max, 255, Callback_Canny_Max);

    waitKey(0);

    return 0;
}

//Canny回调函数
void Callback_Canny_Min(int, void*)
{
    Canny();
}

//Canny回调函数
void Callback_Canny_Max(int, void*)
{
    Canny();
}

python:

# 边缘检测(Sobel、Laplace、Canny)
import cv2 as cv

# Canny最优微分算子
def Canny():
    dst = cv.Canny(img, 100,  255)
    #                   低阈值 高阈值
    cv.imshow("dst", dst)

if __name__ == '__main__':
    # 读取图片
    img = cv.imread("Resource/test5.jpg")
    cv.imshow("img", img)

    # Sobel()         #Sobel一阶微分算子
    # Laplace()       #Laplace二阶微分算子
    Canny()         #Canny最优微分算子

    cv.waitKey(0)

效果

OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)_第4张图片

参考资料

https://www.bilibili.com/video/BV1Fo4y1d7JL?p=34&spm_id_from=pageDriver

你可能感兴趣的:(#,OpenCV,opencv,计算机视觉,边缘计算,图像处理,python)