2019-6-22 opencv图像处理7-边缘检测函数Canny

64 篇文章 3 订阅

对于图像的处理,基本的步骤是这样的:
step1.取得图像数据
step2.将图像进行平滑处理
step3.进行边缘检测,阈值分析
step4.进行形态学的操作
step5.获取某些特征点
step6.分析数据

利用opencv的Canny函数就可以进行边缘检测。

官网参见https://docs.opencv.org/3.4.1/da/d22/tutorial_py_canny.html

测试一下

# -*- coding: cp936 -*-
import cv2

image = cv2.imread('test.jpg')
cv2.namedWindow("Image")

# Canny函数,三个参数:源图像,低阈值,高阈值
image = cv2.Canny(image, 200, 300)

cv2.imshow("Image", image)
cv2.waitKey(0)

在这里插入图片描述
看一下运行效果,左边是原图。

查了Candy函数说明http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.html
Canny 边缘检测算法是 John F. Canny 于1986年开发出来的一个多级边缘检测算法
边缘检测算法优劣的三个主要评价标准是:

  • 低错误率: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
  • 高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近。
  • 最小响应: 图像中的边缘只能标识一次。

Candy算法原理

用代码实现Canny算法过程可以参考https://blog.csdn.net/u012198575/article/details/84846567
主要步骤:

  • 降噪(图像平滑处理-低通滤波器)
    由于边缘检测对图像中的噪声很敏感,第一步是用5x5高斯滤波器(低通滤波器)去除图像中的噪声。参见https://mp.csdn.net/mdeditor/96101079#
  • 计算图像梯度(高通滤波器)
    图像平滑处理后,使用Sobel算子,x和y方向求导(图像梯度Gx和Gy)。根据梯度Gx和Gy然后获得边界的梯度的方向和大小
    Edge_Gradient(G)= G x 2 + G y 2 \sqrt{G_x^2+G_y^2} \quad Gx2+Gy2
    Angle(θ)=tan−1 ( G   y G   x ) \left(\frac{G~y}{G~x} \right) (G xG y)
    梯度的方向总是垂直于边界。梯度方向被归为四类:垂直,水平,和两个对角线。
  • 非极大值抑制。 这一步排除非边缘像素, 仅仅保留了一些细线条(thin edges,候选边缘)。
    在获得梯度的方向和大小之后,应该对整幅图像做一个扫描,去除那些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围具有相同梯度方向的点中最大的。
    在这里插入图片描述
  • 滞后双阈值化 ,高阈值和低阈值。Canny 推荐的高:低阈值比在 2:1 到3:1之间。
    现在要确定那些边界才是真正的边界。这时我们需要设置两个阈值:minVal 和maxVal。当图像的灰度梯度高于maxVal 时被认为是真的边界,那些低于minVal 的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。
    在这里插入图片描述
    上图中,A 高于阈值maxVal 所以是真正的边界点,C 虽然低于maxVal 但高于
    minVal 并且与A 相连,所以也被认为是真正的边界点。而B 就会被抛弃,因
    为他不仅低于maxVal 而且不与真正的边界点相连。所以选择合适的maxVal
    和minVal 对于能否得到好的结果非常重要。
    在这一步一些小的噪声点也会被除去,因为我们假设边界都是一些长的线段。

python中的Canny函数说明如下

Canny(image,threshold1,threshold2,edges=None,apertureSize=None,L2gradient=None)
  • threshold1:int类型的,低阈值
  • threshold2:int类型的,高阈值
  • edeges:单通道存储边缘的输出图像
  • apertureSize:Sobel算子内核(kSize)大小
  • L2gradiend:Bool类型的,真 表示使用更精确的L2范数进行计算(两个方向的倒数的平方再开放),假 表示用L1范数(直接将两个方向导数的绝对值相加)

可以自己写代码来观察阈值变化对图像带来的影响

# -*- coding: cp936 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt

def nothing(x):
    pass

cv2.namedWindow('res')

cv2.createTrackbar('max','res',0,300,nothing)
cv2.createTrackbar('min','res',0,200,nothing)

img = cv2.imread('test.jpg')

maxVal=100
minVal=1

while (1):
    if cv2.waitKey(20) & 0xFF==27: #20ms中如果按下ESC退出循环。27是ESC的ASCII码
        break

    maxVal = cv2.getTrackbarPos('max','res')
    minVal = cv2.getTrackbarPos('min','res')

    if minVal > maxVal:
        edge = cv2.Canny(img,200,300)
       
    else:
        edge = cv2.Canny(img,minVal,maxVal)
    cv2.imshow('res',edge)

cv2.destoryAllWindows()

运行结果
在这里插入图片描述在这里插入图片描述

可以发现,当改变阈值后,图像后渐渐过滤掉一些背景,当然,重在阈值的选取上,当阈值选大的时候,也是会将图像的特征完全损坏的。

opencv中还有其他边缘检测方法,参见https://blog.csdn.net/qq_34711208/article/details/81703341

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值