OpenCv之Canny边界检测(笔记13)

Posted 月疯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCv之Canny边界检测(笔记13)相关的知识,希望对你有一定的参考价值。

 

#Canny边缘检测

canny边缘检测是一种非常流行的边缘检测算法,是John.F.Canny再1986年提出来了的。他是一个很多步构成的算法,我们接下来逐步介绍。

1、噪声去除 由于边缘检测很容易受到噪声的影响,所以第一步是使用5x5的高斯滤波器去除噪声

2、计算图像梯度 对平滑后的图像使用Sobel算子计算水平方向的和竖直方向的一阶导数(图像梯度)(Gx和Gy)。根据得到的这俩福梯度图(Gx和Gy)找到边界的梯度和方向, 公式如下:

G=\\sqrt{Gx^{2}+Gy^{2}}

梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直,水平,和俩个对角线。

 

3、非极大值抑制 再获得梯度的方向和大笑之后,应该对整幅图像做一个扫描,去除那些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围具有相同的梯度方向的点 中最大的。如下所示: 上图当中的数字代表了像素点的梯度强度,箭头方向代表了梯度的方向。以第二排第三个像素点为例,由于梯度方向向上,则将这一点的强度(7)与其上下俩个像素点的强度 (5和4)比较,由于这一点强度最大,则保留。

4、滞后阈值 现在要确定那些边界才是真正的边界。这时我们需要设置俩个阈值:minVal和maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界,那些低于minVal的边界会被抛弃 。如果介于俩者之间的话,就要看这个点是否与某个被确认为真正的边界点相连,如果是就认为它是边界点,如果不是就抛弃。如下图: A高于阈值maxVal所以是真正的边界点,B虽然低于maxVal但高于minVal并且与A相连,所以也被认为是真正的边界点。而C就会被抛弃,因为他不仅低于maxVal而 且不与真正的边界相连。D也会被抛弃,因为低于minVal。所以选择合适的maxVal和minVal对于能否得到好的结果非常重要。在这一步一些小的噪声点也会被除去,因为我们假设边界都是一些 长的线段。

Canny使用 再Opencv中只需要一个激活函数:cv2.Canny(),就可以完成以上几步。让我们看如何使用这个函数。这个函数的第一参数是输入图像。第二和第三个分别是 minVal和maxVal。第四个参数设置用来计算图像梯度的Sobel卷积核的大小,默认值为3.最后一个参数是L2gradient,它可以用来设定求梯度大小方程式。 如果设为True,就会使用我们饿上面提到过的方程:G=\\sqrt{Gx^{2}+Gy^{2}}否则使用方程:G=\\left | Gx^{2} \\right |+\\left | Gy^{2} \\right |,默认值是False。

import numpy as np
import matplotlib.pyplot as plt
import cv2
#图像边缘检测
def show(image):
    plt.imshow(image)
    plt.axis('off')
    plt.show()

def imread(image):
    image=cv2.imread(image)
    #把图像的BGR转换成RGB
    image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    return image
image=imread('im.jpg')
# show(image)
# image=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)

def edge_detection(image,minVal=100,maxVal=200):
    image=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
    edges=cv2.Canny(image,minVal,maxVal)
    plt.imshow(edges,'gray')
    plt.axis('off')
    plt.show()

edge_detection(image)

效果展示:

注意设定边界的阈值的最大值和最小值,对结果影响还是特别大

import numpy as np
import matplotlib.pyplot as plt
import cv2
#图像边缘检测
def show(image):
    plt.imshow(image)
    plt.axis('off')
    plt.show()

def imread(image):
    image=cv2.imread(image)
    #把图像的BGR转换成RGB
    image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    return image
image=imread('im.jpg')
# show(image)
image=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)


image = cv2.GaussianBlur(image,(3,3),0)
Value=[(10,150),(100,200),(180,230)]
plt.figure(figsize=(20,5))
for i,(minVal,maxVal) in enumerate(Value):
    plt.subplot(1,3,i+1)
    edges=cv2.Canny(image,minVal,maxVal)
    edges=cv2.GaussianBlur(edges,(3,3),0)
    plt.imshow(edges,'gray')
    plt.title(str((minVal,maxVal)))
    plt.axis('off')
plt.show()

效果展示:

不知道如何选取阈值:

import numpy as np
import matplotlib.pyplot as plt
import cv2
#图像边缘检测
def show(image):
    plt.imshow(image)
    plt.axis('off')
    plt.show()

def imread(image):
    image=cv2.imread(image)
    #把图像的BGR转换成RGB
    image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    return image
image=imread('im.jpg')
# show(image)
image=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)


#不知道阈值应该如何选取
def auto_canny(image,sigma=0.33):
    v=np.median(image)
    lower=int(max(0,(1.0-sigma)*v))
    upper=int(min(255,(1.0+sigma)*v))
    edged=cv2.Canny(image,lower,upper)
    print(lower,upper)
    return edged

edges=auto_canny(image)
edges=cv2.GaussianBlur(edges,(3,3),0)
plt.imshow(edges,'gray')
plt.axis('off')
plt.show()

效果展示:

 

 

 

 

 

 

 

以上是关于OpenCv之Canny边界检测(笔记13)的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV | OpenCV实战从入门到精通系列三 --canny边缘检测

OpenCV之Canny边缘检测器

OpenCV之Canny边缘检测器

OpenCV学习代码记录——canny边缘检测

OpenCV:Canny 边缘检测器获取 minEnclosureCircle

Canny边缘检测算法(python 实现)