python实现canny边缘检测


Posted in Python onSeptember 14, 2020

canny边缘检测原理

canny边缘检测共有5部分组成,下边我会分别来介绍。

1 高斯模糊(略)

2 计算梯度幅值和方向。

可选用的模板:soble算子、Prewitt算子、Roberts模板等等;

一般采用soble算子,OpenCV也是如此,利用soble水平和垂直算子与输入图像卷积计算dx、dy:

python实现canny边缘检测

进一步可以得到图像梯度的幅值:

python实现canny边缘检测

为了简化计算,幅值也可以作如下近似:

python实现canny边缘检测

角度为:

python实现canny边缘检测

如下图表示了中心点的梯度向量、方位角以及边缘方向(任一点的边缘与梯度向量正交) :

python实现canny边缘检测

θ = θm = arctan(dy/dx)(边缘方向)
α = θ + 90= arctan(dy/dx) + 90(梯度方向)

3、根据角度对幅值进行非极大值抑制

划重点:是沿着梯度方向对幅值进行非极大值抑制,而非边缘方向,这里初学者容易弄混。

例如:3*3区域内,边缘可以划分为垂直、水平、45°、135°4个方向,同样,梯度反向也为四个方向(与边缘方向正交)。因此为了进行非极大值,将所有可能的方向量化为4个方向,如下图:

python实现canny边缘检测

python实现canny边缘检测

即梯度方向分别为

α = 90

α = 45

α = 0

α = -45

非极大值抑制即为沿着上述4种类型的梯度方向,比较3*3邻域内对应邻域值的大小:

python实现canny边缘检测

在每一点上,领域中心 x 与沿着其对应的梯度方向的两个像素相比,若中心像素为最大值,则保留,否则中心置0,这样可以抑制非极大值,保留局部梯度最大的点,以得到细化的边缘。

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

1选取系数TH和TL,比率为2:1或3:1。(一般取TH=0.3或0.2,TL=0.1);

2 将小于低阈值的点抛弃,赋0;将大于高阈值的点立即标记(这些点为确定边缘 点),赋1或255;

3将小于高阈值,大于低阈值的点使用8连通区域确定(即:只有与TH像素连接时才会被接受,成为边缘点,赋 1或255)

python 实现

import cv2
import numpy as np
m1 = np.array([[1, 0, -1], [2, 0, -2], [1, 0, -1]])
m2 = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
from matplotlib import pyplot as plt
# 第一步:完成高斯平滑滤波
img = cv2.imread("B9064CF1D57871735CE11A0F368DCF27.jpg", 0)
sobel = cv2.Canny(img, 50, 100)
cv2.namedWindow('5', 0)
cv2.resizeWindow("5", 640, 480)
cv2.imshow("5", sobel) # 角度值灰度图
img = cv2.GaussianBlur(img, (3, 3), 2)
# 第二步:完成一阶有限差分计算,计算每一点的梯度幅值与方向
img1 = np.zeros(img.shape, dtype="uint8") # 与原图大小相同
theta = np.zeros(img.shape, dtype="float") # 方向矩阵原图像大小
img = cv2.copyMakeBorder(img, 1, 1, 1, 1, borderType=cv2.BORDER_REPLICATE)
rows, cols = img.shape
for i in range(1, rows - 1):
for j in range(1, cols - 1):
Gy = [np.sum(m2 * img[i - 1:i + 2, j - 1:j + 2])]
#Gy = (np.dot(np.array([1, 1, 1]), (m2 * img[i - 1:i + 2, j - 1:j + 2]))).dot(np.array([[1], [1], [1]]))
Gx = [np.sum(m1 * img[i - 1:i + 2, j - 1:j + 2])]
#Gx = (np.dot(np.array([1, 1, 1]), (m1 * img[i - 1:i + 2, j - 1:j + 2]))).dot(np.array([[1], [1], [1]]))
if Gx[0] == 0:
theta[i - 1, j - 1] = 90
continue
else:
temp = ((np.arctan2(Gy[0], Gx[0])) * 180 / np.pi)+90
if Gx[0] * Gy[0] > 0:
if Gx[0] > 0:
# 第一象线
theta[i - 1, j - 1] = np.abs(temp)
else:
# 第三象线
theta[i - 1, j - 1] = (np.abs(temp) - 180)
if Gx[0] * Gy[0] < 0:
if Gx[0] > 0:
# 第四象线
theta[i - 1, j - 1] = (-1) * np.abs(temp)
else:
# 第二象线
theta[i - 1, j - 1] = 180 - np.abs(temp)

img1[i - 1, j - 1] = (np.sqrt(Gx[0] ** 2 + Gy[0] ** 2))
for i in range(1, rows - 2):
for j in range(1, cols - 2):
if (((theta[i, j] >= -22.5) and (theta[i, j] < 22.5)) or
((theta[i, j] <= -157.5) and (theta[i, j] >= -180)) or
((theta[i, j] >= 157.5) and (theta[i, j] < 180))):
theta[i, j] = 0.0
elif (((theta[i, j] >= 22.5) and (theta[i, j] < 67.5)) or
((theta[i, j] <= -112.5) and (theta[i, j] >= -157.5))):
theta[i, j] = -45.0
elif (((theta[i, j] >= 67.5) and (theta[i, j] < 112.5)) or
((theta[i, j] <= -67.5) and (theta[i, j] >= -112.5))):
theta[i, j] = 90.0
elif (((theta[i, j] >= 112.5) and (theta[i, j] < 157.5)) or
((theta[i, j] <= -22.5) and (theta[i, j] >= -67.5))):
theta[i, j] = 45.0
'''
for i in range(1, rows - 1):
for j in range(1, cols - 1):
Gy = [np.sum(m2 * img[i - 1:i + 2, j - 1:j + 2])]
#Gy = (np.dot(np.array([1, 1, 1]), (m2 * img[i - 1:i + 2, j - 1:j + 2]))).dot(np.array([[1], [1], [1]]))
Gx = [np.sum(m1 * img[i - 1:i + 2, j - 1:j + 2])]
#Gx = (np.dot(np.array([1, 1, 1]), (m1 * img[i - 1:i + 2, j - 1:j + 2]))).dot(np.array([[1], [1], [1]]))
if Gx[0] == 0:
theta[i - 1, j - 1] = 90
continue
else:
temp = (np.arctan2(Gy[0], Gx[0])) * 180 / np.pi)
if Gx[0] * Gy[0] > 0:
if Gx[0] > 0:
# 第一象线
theta[i - 1, j - 1] = np.abs(temp)
else:
# 第三象线
theta[i - 1, j - 1] = (np.abs(temp) - 180)
if Gx[0] * Gy[0] < 0:
if Gx[0] > 0:
# 第四象线
theta[i - 1, j - 1] = (-1) * np.abs(temp)
else:
# 第二象线
theta[i - 1, j - 1] = 180 - np.abs(temp)

img1[i - 1, j - 1] = (np.sqrt(Gx[0] ** 2 + Gy[0] ** 2))
for i in range(1, rows - 2):
for j in range(1, cols - 2):
if (((theta[i, j] >= -22.5) and (theta[i, j] < 22.5)) or
((theta[i, j] <= -157.5) and (theta[i, j] >= -180)) or
((theta[i, j] >= 157.5) and (theta[i, j] < 180))):
theta[i, j] = 90.0
elif (((theta[i, j] >= 22.5) and (theta[i, j] < 67.5)) or
((theta[i, j] <= -112.5) and (theta[i, j] >= -157.5))):
theta[i, j] = 45.0
elif (((theta[i, j] >= 67.5) and (theta[i, j] < 112.5)) or
((theta[i, j] <= -67.5) and (theta[i, j] >= -112.5))):
theta[i, j] = 0.0
elif (((theta[i, j] >= 112.5) and (theta[i, j] < 157.5)) or
((theta[i, j] <= -22.5) and (theta[i, j] >= -67.5))):
theta[i, j] = -45.0

'''
# 第三步:进行 非极大值抑制计算
img2 = np.zeros(img1.shape) # 非极大值抑制图像矩阵

for i in range(1, img2.shape[0] - 1):
for j in range(1, img2.shape[1] - 1):
# 0度j不变
if (theta[i, j] == 0.0) and (img1[i, j] == np.max([img1[i, j], img1[i + 1, j], img1[i - 1, j]])):
img2[i, j] = img1[i, j]

if (theta[i, j] == -45.0) and img1[i, j] == np.max([img1[i, j], img1[i - 1, j - 1], img1[i + 1, j + 1]]):
img2[i, j] = img1[i, j]

if (theta[i, j] == 90.0) and img1[i, j] == np.max([img1[i, j], img1[i, j + 1], img1[i, j - 1]]):
img2[i, j] = img1[i, j]

if (theta[i, j] == 45.0) and img1[i, j] == np.max([img1[i, j], img1[i - 1, j + 1], img1[i + 1, j - 1]]):
img2[i, j] = img1[i, j]

# 第四步:双阈值检测和边缘连接
img3 = np.zeros(img2.shape) # 定义双阈值图像
# TL = 0.4*np.max(img2)
# TH = 0.5*np.max(img2)
TL = 50
TH = 100
# 关键在这两个阈值的选择
for i in range(1, img3.shape[0] - 1):
for j in range(1, img3.shape[1] - 1):
if img2[i, j] < TL:
img3[i, j] = 0
elif img2[i, j] > TH:
img3[i, j] = 255
elif ((img2[i + 1, j] < TH) or (img2[i - 1, j] < TH) or (img2[i, j + 1] < TH) or
(img2[i, j - 1] < TH) or (img2[i - 1, j - 1] < TH) or (img2[i - 1, j + 1] < TH) or
(img2[i + 1, j + 1] < TH) or (img2[i + 1, j - 1] < TH)):
img3[i, j] = 255

cv2.namedWindow('1', 0)
cv2.resizeWindow("1", 640, 480)
cv2.namedWindow('2', 0)
cv2.resizeWindow("2", 640, 480)
cv2.namedWindow('3', 0)
cv2.resizeWindow("3", 640, 480)
cv2.namedWindow('4', 0)
cv2.resizeWindow("4", 640, 480)
cv2.imshow("1", img) # 原始图像
cv2.imshow("2", img1) # 梯度幅值图
cv2.imshow("3", img2) # 非极大值抑制灰度图
cv2.imshow("4", img3) # 最终效果图
cv2.waitKey(0)

运行结果如下

python实现canny边缘检测

python实现canny边缘检测

以上就是python实现canny边缘检测的详细内容,更多关于canny边缘检测的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python中实现对list做减法操作介绍
Jan 09 Python
python 统计代码行数简单实例
May 04 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
Jun 02 Python
linecache模块加载和缓存文件内容详解
Jan 11 Python
解决python 输出是省略号的问题
Apr 19 Python
python 遍历目录(包括子目录)下所有文件的实例
Jul 11 Python
Python实现的拉格朗日插值法示例
Jan 08 Python
详解Python3迁移接口变化采坑记
Oct 11 Python
Python爬虫谷歌Chrome F12抓包过程原理解析
Jun 04 Python
mac系统下安装pycharm、永久激活、中文汉化详细教程
Nov 24 Python
详解python3 GUI刷屏器(附源码)
Feb 18 Python
Python利用folium实现地图可视化
May 23 Python
Python gevent协程切换实现详解
Sep 14 #Python
通过实例了解python__slots__使用方法
Sep 14 #Python
python如何遍历指定路径下所有文件(按按照时间区间检索)
Sep 14 #Python
详解python实现可视化的MD5、sha256哈希加密小工具
Sep 14 #Python
Python利用pip安装tar.gz格式的离线资源包
Sep 14 #Python
Python tkinter制作单机五子棋游戏
Sep 14 #Python
python安装cx_Oracle和wxPython的方法
Sep 14 #Python
You might like
PHP使用Alexa API获取网站的Alexa排名例子
2014/06/12 PHP
PHP将URL转换成短网址的算法分享
2016/09/13 PHP
阿里云Win2016安装Apache和PHP环境图文教程
2018/03/11 PHP
php自动加载代码实例详解
2021/02/26 PHP
Prototype1.6 JS 官方下载地址
2007/11/30 Javascript
jQuery的实现原理的模拟代码 -4 重要的扩展函数 extend
2010/08/03 Javascript
javascript的函数、创建对象、封装、属性和方法、继承
2011/03/10 Javascript
拉动滚动条加载数据的jquery代码
2012/05/03 Javascript
jquery简单瀑布流实现原理及ie8下测试代码
2013/01/23 Javascript
javascript清空table表格的方法
2015/05/14 Javascript
WEB前端开发都应知道的jquery小技巧及jquery三个简写
2015/11/15 Javascript
基于node.js制作简单爬虫教程
2017/06/29 Javascript
详解node如何让一个端口同时支持https与http
2017/07/04 Javascript
vue使用Proxy实现双向绑定的方法示例
2019/03/20 Javascript
在Vue中用canvas实现二维码和图片合成海报的方法
2019/06/10 Javascript
JavaScript学习教程之cookie与webstorage
2019/06/23 Javascript
vue使用自定义指令实现拖拽
2021/01/29 Javascript
在vue中使用cookie记住用户上次选择的实例(本次例子中为下拉框)
2020/09/11 Javascript
详解Python中for循环的使用方法
2015/05/14 Python
pygame实现弹力球及其变速效果
2017/07/03 Python
Python中矩阵创建和矩阵运算方法
2018/08/04 Python
Python生成MD5值的两种方法实例分析
2019/04/26 Python
flask框架自定义过滤器示例【markdown文件读取和展示功能】
2019/11/08 Python
Django ModelForm操作及验证方式
2020/03/30 Python
环境科学专业研究生求职信
2013/10/02 职场文书
车间操作工岗位职责
2013/12/19 职场文书
大学生怎样写好自荐信
2014/02/25 职场文书
行政专员的岗位职责
2014/03/10 职场文书
剪彩仪式主持词
2014/03/19 职场文书
母校寄语大全
2014/04/10 职场文书
大队干部竞选演讲稿
2014/04/28 职场文书
团队精神的演讲稿
2014/05/14 职场文书
离职感谢信
2015/01/21 职场文书
幼儿园小班开学寄语
2015/05/27 职场文书
法制教育观后感
2015/06/17 职场文书
2019个人半年工作总结
2019/06/21 职场文书