基于OpenCv的图像Canny边缘检测

时间:2024-10-05 16:02:58

⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计3077字,阅读大概需要3分钟
????更多学习内容, 欢迎????关注????【文末】我的个人微信公众号:不懂开发的程序猿
个人网站/

❗❗❗知识付费,????止白嫖,有需要请后台私信或【文末】个人微信公众号联系我

基于OpenCv的图像Canny边缘检测

  • 基于OpenCv的图像Canny边缘检测
    • 任务需求
    • 任务目标
      • 1、掌握使用Canny算子的步骤
      • 2、掌握基于OpenCv进行Canny边缘检测
    • 任务环境
      • 1、jupyter开发环境
      • 2、OpenCv
      • 3、python3.6
    • 任务实施过程
      • 一、Canny边缘检测
        • 1.导入所需要的工具包和图像
        • 2.高斯滤波器平滑图像
        • 边缘检测
        • 算子与其他边缘检测算法对比
      • 二、任务小结
  • 说明

基于OpenCv的图像Canny边缘检测

任务需求

边缘检测是图像处理与识别中最基础、最重要的内容之一。一幅图像就是一个信息系统,其大量信息是由它的轮廓边缘提供的。对图像分析和理解的第一步常常是边缘检测。
例如,车牌照片预处理是汽车牌照识别系统中的一个重要的环节,预处理的好坏对车牌系统识别率影响很大,可以利用边缘检测对车牌定位得到车牌区域,获取轮廓,如下图。

在这里插入图片描述

任务目标

1、掌握使用Canny算子的步骤

2、掌握基于OpenCv进行Canny边缘检测

任务环境

1、jupyter开发环境

2、OpenCv

3、python3.6

任务实施过程

一、Canny边缘检测

Canny 边缘检测算法是一个多级边缘检测算法,也被很多人认为是边缘检测的最优算法。

Canny边缘检测步骤如下:

  • 1.用高斯滤波器平滑图像:使用高斯滤波器消除图像中的噪声
  • 2.用一阶偏导有限差分计算梯度幅值和方向:一般使用Sobel算子核在水平和垂直方向上对平滑的图像进行滤波
  • 3.对梯度幅值进行非极大值抑制:对于梯度幅值图像,仅保留梯度方向的极大值点

在这里插入图片描述

在梯度方向的沿线上检测该点是否为局部极大值,得到的结果图像包含边缘的宽度为1个像素

  • 4.用双阈值算法检测和连接边缘

梯度值>maxVal:则为边界(强边界)

minVal<梯度值<maxVal:如果连接有强边界则保留,否则舍弃

梯度值<minVal:不是边界

在这里插入图片描述

1.导入所需要的工具包和图像
import cv2 # 导入opencv
import matplotlib.pyplot as plt # 导入绘图模块
import numpy as np # 导入numpy库
from utils import im_show # 导入显示图像函数
# 绘制图像直接展示,不用调用()
%matplotlib inline 
# 用来正常显示中文标签
plt.rc('font',family="SimHei")
# 读取图像,0 按单通道的方式读入图像,即灰白图像
img = cv2.imread(r'./experiment/data/',0)
# 设置画布大小
plt.figure(figsize=(6,6))
# 显示图像
im_show('原图像',img)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

2.高斯滤波器平滑图像

先对原始图像使用 3 ∗ 3 3*3 33高斯卷积核和 5 ∗ 5 5*5 55高斯卷积核对图像进行平滑处理

(img, ksize,sigmaX,sigmaY)

  • img:原图像
  • ksize:表示进行高斯滤波的卷积核大小
  • sigmaX:X 方向的高斯核标准差
  • sigmaY:Y 方向的高斯核标准差,如果仅指定了sigmaX,则sigmaY与sigmaX相同。如果两者都为 0,则可以根据 ksize 来计算得到。
# 高斯滤波,使用不同尺寸的高斯卷积核对图像进行卷积平滑
blur3 = cv2.GaussianBlur(img, (3, 3), 0) 
blur5 = cv2.GaussianBlur(img, (5, 5), 0) 
plt.figure(figsize=(12,12))
# 显示图像进行高斯平滑后的结果
im_show('原图像高斯平滑后的图像',np.hstack((blur3,blur5)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

边缘检测

(image, threshold1, threshold2, apertureSize)

  • image:原图像
  • threshold1:阈值1(小)
  • threshold2:阈值2(大)
  • apertureSize:可选参数,Sobel算子的大小
# 使用Canny函数进行边缘检测
# 放入高斯平滑后的图像blur3和blur5
# 设置双阈值 最小阈值50 最大阈值150
canny1 = cv2.Canny(blur3, 50, 150)
canny2 = cv2.Canny(blur5, 50, 150)
# 设置双阈值 最小阈值50 最大阈值100
canny3 = cv2.Canny(blur3, 50, 100)
# 设置双阈值 最小阈值80 最大阈值100
canny4 = cv2.Canny(blur5, 80, 150)
# 创建一个列表l,放入四个Canny边缘结果
l = [canny1,canny2,canny3,canny4]
# 创建一个列表g,放入四个高斯平滑高斯核尺寸
g = ['3*3','5*5','3*3','5*5']
# 创建一个列表y,放入Canny函数中设置的大、小阈值
y = ['(50,150)','(50,150)','(50,100)','(80,150)']
plt.figure(figsize=(12,12))
# 使用for循环,绘制四个边缘结果的图像
for i in range(4):
    plt.subplot(2,2,i+1)
    im_show('1',l[i])
    # 设置子图标题和字体大小
    plt.title('高斯滤波尺寸为{}和双阈值为{}的边缘检测'.format(g[i],y[i]),fontsize=15)
# 调整子图距离
plt.tight_layout()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述

在这里插入图片描述

设置大小阈值分别为 T 1 T_1 T1, T 2 T_2 T2,对于同一个高斯核对图像进行高斯平滑后:

  • 大于 T 2 T_2 T2的边缘是强边界, T 2 T_2 T2的值减小,高阈值宽松,得到的强边缘变多,总体边缘变多。
  • 大于 T 1 T_1 T1小于 T 2 T_2 T2的边缘是弱边界,弱边界与强边界相连的部分是边缘, T 1 T_1 T1的值增大,低阈值得到的弱边界变少,弱边界与强边界相连的部分也随之变少,总体边缘变少。
  • 一般推荐的高低阈值比值为 T 2 T_2 T2: T 1 T_1 T1 = 3:1/2:1
算子与其他边缘检测算法对比

对于使用高斯平滑(高斯核: 3 ∗ 3 3*3 33)后的图像进行不同方法的边缘检测并查看其检测结果

# 1.图像梯度获取边缘
# 首先将图像二值化,使用阈值函数,设置阈值为60,像素值超过60则赋值为255
_,Thr_img = cv2.threshold(blur3,60,255,cv2.THRESH_BINARY)
# 设置5*5卷积核
kernel = np.ones((5,5),np.uint8)
# 放入二值化后的图像,cv2.MORPH_GRADIENT表示图像梯度计算:膨胀-腐蚀
gradient = cv2.morphologyEx(Thr_img, cv2.MORPH_GRADIENT, kernel)

# 2.高斯拉普拉斯(LoG)边缘检测:高斯模糊+Laplacian
# cv2.CV_64F输出图像深度(数据类型),允许结果是负值
# 需要用convertScaleAbs()函数将其转回原来的uint8形式
log = cv2.Laplacian(blur3,cv2.CV_64F,ksize=3)
log = cv2.convertScaleAbs(log)

# 算子边缘检测
# 参数1,0 为只在x方向求一阶导数
sobel_x = cv2.Sobel(blur3,cv2.CV_64F,1,0,ksize=3)
sobel_x = cv2.convertScaleAbs(sobel_x)
# 参数0,1 为只在y方向求一阶导数
sobel_y = cv2.Sobel(blur3,cv2.CV_64F,0,1,ksize=3)
sobel_y = cv2.convertScaleAbs(sobel_y)
# 将两个方向卷积得到的边缘进行图像融合
sobelxy = cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0)

# 创建一个列表,放入四个得到的边缘结果
edge_list = [canny3,gradient,log,sobelxy]
# 创建一个列表,放入4个算子名
label = ['Canny','Gradient','LoG','Sobel']
plt.figure(figsize=(12,12))
# 使用for循环,绘制4个边缘的结果
for i in range(4):
    plt.subplot(2,2,i+1)
    im_show('1',edge_list[i])
    # 设置子图标题,设置标题字体大小
    plt.title('{}算子边缘检测结果'.format(label[i]),fontsize = 15)
# 调整子图之间的距离
plt.tight_layout()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在这里插入图片描述
在这里插入图片描述

二、任务小结

本次实验主要完成基于Canny算子对图像边缘的检测。可以看到相对于形态学梯度计算、LoG算子、Sobel算子得到的图像边缘,Canny算子是一个具有滤波、最强和检测的多阶段的优化算子,有高定位精度、低误判率、抑制虚假边缘的特点,适用于高噪声图像。

通过本次实验需要掌握以下内容:

  • 1.掌握Canny算子进行边缘检测的步骤
  • 2.掌握不同的Canny算子阈值对图像边缘的检测结果的影响

–end–

说明

本实验(项目)/论文若有需要,请后台私信或【文末】个人微信公众号联系我