目录
一、基础理论
1、作用及介绍
1、原理
2、过程
3、Canny函数
二、回调函数及总代码
效果
参考资料
Canny边缘检测是非常流行的边缘检测算法,被认为是最优的边缘检测算法。
首先在x和y方向求一阶导数,然后组合为4个方向的导数,这些方向导数达到局部最大值的点就是组成边缘的候选点。
优点:分别用两种不同的阈值检测强边缘和弱边缘。(当且仅当强边缘与弱边缘相连时,才将若边缘输出到图像中)
四步法:
第一步,图像降噪。高斯滤波。
第二步,计算图像梯度,sobel算子,计算梯度大小和方向。
梯度方向总是与边缘垂直,梯度方向有四类:垂直、水平、两个对角线方向。
第三步,非极大值抑制(保留极大值)。利用梯度方向像素判断是否为边界点,去除非边界点。(边缘变“瘦”)
第四步,双阈值筛选(保留极大值)。设置两个阈值,确定最终边界。
现在要确定真正的边界。我们设置两个阈值: minVal和 maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界,低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。(和极大值相连则保留)如下图:A和C视为边界,B不视为边界。
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)
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)
https://www.bilibili.com/video/BV1Fo4y1d7JL?p=34&spm_id_from=pageDriver