使用OpenCV的cv2.Canny()函数实现图像边缘检测——Python学习OpenCV系列(六十八)

【1】引言

前序学习进程中,在对图像进行边缘识别的基础上,先后进行了边缘轮廓绘制,矩形标注、圆形标注和凸包标注。相关文章包括且不限于:

python学opencv|读取图像(六十四)使用cv2.findContours()函数+cv2.drawContours()函数实现图像轮廓识别和标注-CSDN博客

python学opencv|读取图像(六十五)使用cv2.boundingRect()函数实现图像轮廓矩形标注-CSDN博客

python学opencv|读取图像(六十六)使用cv2.minEnclosingCircle函数实现图像轮廓圆形标注-CSDN博客

实际上,除了按照边缘轮廓来绘制线条进行标注外,其他的三种标注方式都不够精确,而且对图像的构成要求很高。但按照边缘轮廓来绘制线条进行标注,需要调用两个函数,先识别边缘,再绘制线条,实际上的描边效果会有一些线条的堆砌,整体效果依然不够精准和高效。

为此,如果有一种直接进行边缘检测然后标注的方法,将会使得图像识别的效果大大增强。这就是本次课程学习的目标:使用cv2.Canny()函数实现图像边缘检测。

【2】官网教程

点击下述链接,直达cv2.Canny()函数的官网教程:

OpenCV: Feature Detection

官网页面对 cv2.Canny()函数的说明为:

图1  官网页面对 cv2.Canny()函数的说明

相应的,官网页面对 cv2.Canny()函数的参数说明为:

    cv.Canny(    

image                      #输入图像

threshold1               #第一个阈值

threshold2               #第二个阈值

edges                      #输出图像

apertureSize           #sober operator的尺寸,可选参数,暂无需关注

L2gradient   )

关于 apertureSize 对应的sober operator的尺寸,可以通过下述链接了解:

OpenCV: Sobel Derivatives

【3】代码测试

首先引入必要模块,进行图像读取:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片
src = cv.imread('srcoo.png') #读取图像

然后进行图像边缘检测:

#边缘检测
r1=cv.Canny(src,10,50)  #边缘检测
r2=cv.Canny(src,100,150) #边缘检测
r3=cv.Canny(src,255,500) #边缘检测
r4=cv.Canny(src,255,800) #边缘检测

上述不同的检测输出,是由于上下的阈值不同。

然后进行图像显示和保存:

#显示和保存图像
r5=np.hstack((r3,r4))
cv.imshow('r',src)
cv.imshow('r1',r1)
cv.imshow('r2',r2)
cv.imshow('r3',r3)
cv.imshow('r5',r5)

cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

图像运行相关的图像有:

图2 初始图像

图3 阈值(10,50)对应检测效果Canny-r1.png 

图4 阈值(100,150)对应检测效果Canny-r2.png 

图5 阈值(255,500)对应检测效果Canny-r3.png 

图5 阈值(255,500)和(255,800)对应检测效果Canny-r5.png 

由图2到图5可见,随之阈值的增大,图像的细节越来越少;随之阈值差距的增大,图像的细节也越来越少。

此时的完整代码为:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片
src = cv.imread('srcoo.png') #读取图像

#边缘检测
r1=cv.Canny(src,10,50)  #边缘检测
r2=cv.Canny(src,100,150) #边缘检测
r3=cv.Canny(src,255,500) #边缘检测
r4=cv.Canny(src,255,800) #边缘检测
#b=cv.split(r2)
#g=cv.split(r4)
#print('r3.shape=',r3.shape)
#print('b=',b)
#print('g=',g)

#显示和保存图像
r5=np.hstack((r3,r4))
cv.imshow('r',src)
cv.imshow('r1',r1)
cv.imwrite('Canny-r1.png', r1) #保存图像
cv.imshow('r2',r2)
cv.imwrite('Canny-r2.png', r2) #保存图像
cv.imshow('r3',r3)
cv.imwrite('Canny-r3.png', r3) #保存图像
cv.imshow('r5',r5)
cv.imwrite('Canny-r5.png', r5) #保存图像

cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

【4】细节说明

如果仔细思考,会发现阈值可以使用超过255的数据。

这是因为cv2.Canny函数对应的算法中:阈值的低值是进行阈值转化的判断开关,而阈值的高值则直接影响了如何进行阈值转化。官网的说明页中,没有对阈值进行限制。

The smallest value between threshold1 and threshold2 is used for edge linking. The largest value is used to find initial segments of strong edges

【5】总结

掌握了python+opencv通过使用cv2.Canny()函数对图像进行边缘检测的技巧。

作者:西猫雷婶

物联沃分享整理
物联沃-IOTWORD物联网 » 使用OpenCV的cv2.Canny()函数实现图像边缘检测——Python学习OpenCV系列(六十八)

发表回复