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分析nignx访问日志脚本分享
Feb 26 Python
Python中zfill()方法的使用教程
May 20 Python
python获取各操作系统硬件信息的方法
Jun 03 Python
python中利用xml.dom模块解析xml的方法教程
May 24 Python
Django学习笔记之ORM基础教程
Mar 27 Python
Python使用min、max函数查找二维数据矩阵中最小、最大值的方法
May 15 Python
Python日期时间对象转换为字符串的实例
Jun 22 Python
一百行python代码将图片转成字符画
Feb 19 Python
python导入不同目录下的自定义模块过程解析
Nov 18 Python
keras的ImageDataGenerator和flow()的用法说明
Jul 03 Python
PyTorch实现重写/改写Dataset并载入Dataloader
Jul 14 Python
Django与AJAX实现网页动态数据显示的示例代码
Feb 24 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
使用VisualStudio开发php的图文设置方法
2010/08/21 PHP
php异常处理使用示例
2014/02/25 PHP
php动态生成缩略图并输出显示的方法
2015/04/20 PHP
php读取txt文件并将数据插入到数据库
2016/02/23 PHP
PHP开发之用微信远程遥控服务器
2018/01/25 PHP
Laravel 验证码认证学习记录小结
2019/12/20 PHP
初探jquery——表单应用范例
2007/02/20 Javascript
List Installed Software Features
2007/06/11 Javascript
Javascript Object.extend
2010/05/18 Javascript
JQuery 学习技巧总结
2010/05/21 Javascript
javascript基础知识大集锦(二) 推荐收藏
2011/01/13 Javascript
js replace替换所有匹配的字符串
2014/02/13 Javascript
JavaScript通过prototype给对象定义属性用法实例
2015/03/23 Javascript
AngularJS ng-app 指令实例详解
2016/07/30 Javascript
jquery仿京东侧边栏导航效果
2017/03/02 Javascript
如何解决vue与传统jquery插件冲突
2017/03/20 Javascript
微信小程序实现瀑布流布局与无限加载的方法详解
2017/05/12 Javascript
vue 父组件调用子组件方法及事件
2018/03/29 Javascript
vue-router 实现导航守卫(路由卫士)的实例代码
2018/09/02 Javascript
解决angularJS中input标签的ng-change事件无效问题
2018/09/13 Javascript
阿望教你用vue写扫雷小游戏
2020/01/20 Javascript
easyUI使用分页过滤器对数据进行分页操作实例分析
2020/06/01 Javascript
[01:28]2014DOTA2国际邀请赛中国区预选赛四大豪门直升机抵达会场
2014/05/24 DOTA
Python实现扫描指定目录下的子目录及文件的方法
2014/07/16 Python
python实现C4.5决策树算法
2018/08/29 Python
Python自动化测试笔试面试题精选
2020/03/12 Python
用python打开摄像头并把图像传回qq邮箱(Pyinstaller打包)
2020/05/17 Python
Python logging模块进行封装实现原理解析
2020/08/07 Python
Python编写万花尺图案实例
2021/01/03 Python
中药学自荐信
2014/06/15 职场文书
机械制造专业大学生自我鉴定
2014/09/19 职场文书
2014党员自我评议表范文
2014/09/20 职场文书
中学教师个人总结
2015/02/10 职场文书
领导干部学习三严三实心得体会
2016/01/05 职场文书
python 调用js的四种方式
2021/04/11 Python
k8s部署redis cluster集群的实现
2021/06/24 Redis