Python利用OpenCV和skimage实现图像边缘检测
作者:叶庭云 发布时间:2023-01-27 01:08:43
一、简介
提取图片的边缘信息是底层数字图像处理的基本任务之一。边缘信息对进一步提取高层语义信息有很大的影响。大部分边缘检测算法都是上个世纪的了,OpenCV 的使用的算法是 Canny 边缘检测算法,大概是在 1986 年由 John F. Canny 提出了,似乎说明边缘检测算法的研究已经到达了瓶颈期。跟人眼系统相比,边缘检测算法仍然逊色不少。
Canny 边缘检测算法是比较出色的算法,也是一种多步算法,可用于检测任何输入图像的边缘。利用它检测图像边缘时主要有以下步骤:
应用高斯滤波来平滑图像,目的是去除噪声。
计算高斯滤波器的导数,计算图像像素的梯度,得到沿x和y维度的梯度。
应用非最大抑制(non-maximum suppression)技术来消除边缘误检(本来不是但检测出来是)
应用双阈值的方法来决定可能的(潜在的)边界
利用滞后阈值方法保留高于梯度幅值的像素,忽略低于低阈值的像素,实现边缘追踪。
Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:
最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;
最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;
检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。
为了满足这些要求 Canny 使用了变分法(calculus of variations),这是一种寻找优化特定功能的函数的方法。最优检测使用四个指数函数项表示,它可以由高斯函数的一阶导数来近似。
二、opencv 实践
cv2.Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None):
# 用自定义梯度
cv2.Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]]) -> edges
image:参表示8位输入图像
threshold1:设置的低阈值
threshold2:设置的高阈值
edges:输出边缘图像,单通道8位图像
apertureSize:Sobel算子的大小
L2gradient:一个布尔值,如果为真,则使用更精确的 L2 范数进行计算(即两个方向的倒数的平方和再开方),否则使用 L1 范数(直接将两个方向导数的绝对值相加)。
def opencv_canny(image):
# 高斯模糊 降低噪声
blurred = cv.GaussianBlur(image, (5, 5), 0)
# 转为灰度图像
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
# 计算x y 方向梯度
grad_x = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
edge_output = cv.Canny(grad_x, grad_y, 60, 120)
# 英文字体 Times New Roman
plt.rcParams['font.sans-serif'] = ['Times New Roman']
# 可视化结果
plt.figure(figsize=(8, 4), dpi=500)
plt.subplot(121)
plt.imshow(gray, cmap='gray')
plt.title('Original Image', fontsize=18)
plt.xticks([]), plt.yticks([])
plt.subplot(122)
plt.imshow(edge_output, cmap='gray')
plt.title('Edge Image', fontsize=18)
plt.xticks([]), plt.yticks([])
plt.savefig("002.png", dpi=500)
plt.show()
if __name__ == "__main__":
# 读取图像 传入
src = cv.imread("Lenna.png")
opencv_canny(src)
结果如下:
三、skimage 实践
import numpy as np
from skimage.io import imread
from skimage.feature import canny
import matplotlib.pyplot as plt
# 读取图像
img = imread("Lenna.png", as_gray=True)
# 高斯模糊 降低噪声
img = cv.GaussianBlur(img, (5, 5), 0)
# Canny边缘检测
edges = canny(img, sigma=1.6)
# 可视化结果
plt.rcParams['font.sans-serif'] = ['Times New Roman']
plt.figure(figsize=(8, 4), dpi=500)
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('Original Image', fontsize=18)
plt.xticks([]), plt.yticks([])
plt.subplot(122)
plt.imshow(edges, cmap='gray')
plt.title('Edge Image', fontsize=18)
plt.xticks([]), plt.yticks([])
plt.show()
结果如下:
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage as ndi
from skimage import feature
# 产生带有噪声的举行图案
im = np.zeros((128, 128))
im[32:-32, 32:-32] = 1
im = ndi.rotate(im, 15, mode='constant') # 旋转一定角度
im = ndi.gaussian_filter(im, 4)
im += 0.2 * np.random.random(im.shape)
# Compute the Canny filter for two values of sigma
edges1 = feature.canny(im, sigma=1)
edges2 = feature.canny(im, sigma=3)
# display results
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 4),
sharex=True, sharey=True, dpi=500)
ax1.imshow(im, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('Noisy image', fontsize=20)
ax2.imshow(edges1, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title(r'Canny filter, $\sigma=1$', fontsize=20)
ax3.imshow(edges2, cmap=plt.cm.gray)
ax3.axis('off')
ax3.set_title(r'Canny filter, $\sigma=3$', fontsize=20)
fig.tight_layout()
plt.show()
结果如下:
skimage 库中函数
skimage.feature.canny(image, sigma=1.0,
low_threshold=None, high_threshold=None,
mask=None, use_quantiles=False)
sigma:高斯滤波器的标准差
low_threshold:Canny算法最后一步中,小于该阈值的像素直接置为0
high_threshold:Canny算法最后一步中,大于该阈值的像素直接置为255
来源:https://blog.csdn.net/fyfugoyfa/article/details/122942507


猜你喜欢
- 项目中要对短文本进行相似度估计,word2vec是一个很火的工具。本文就word2vec的训练以及加载进行了总结。word2vec的原理就不
- 在做Django项目的过程中, 无法进入pycharm提供的Run manager.py Task交互环境出现这种问题是因为Pycharm无
- python 字符串和日期之间转换 StringAndDate &nb
- 解决方法:1。 改表法。可能是你的帐号不允许从远程登陆,只能在localhost。这个时候只要在localhost的那台电脑,登入mysql
- 环境变量配置首先需要将anaconda的路径配置进环境变量中,我是用户变量和系统变量都配置了。我的anaconda安装在D:\Anacond
- 首先,我们知道一副牌里有54张牌,然后牌里的数字是从 3 - 2 的里面总共有13张牌,然后 4 中花色 分别是 ♠?
- SQL中的单记录函数1.ASCII返回与指定的字符对应的十进制数;SQL> select ascii('A') A,a
- 从事DBA的行业也有两年多了,在数据备份上无论是理论和实践上,都积
- 1,打开cmd安装PyQt5pip install pyqt52,PyQt5不再提供Qt Designer等工具,所以需要再安装pyqt5-
- 先在GitHub找到PHPMailer 并下载https://github.com/PHPMailer/PHPMailer//PHPMail
- 当在一个分支的开发工作未完成,却又要切换到另外一个分支进行开发的时候,除了commit原分支的代码改动的方法外,我觉得git st
- 如下所示:1. 在PyCharm下安装pyinstaller2. 在Terminal下输入:“pyinstaller -F -w *.py”
- OVER的定义OVER用于为行定义一个窗口,它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的
- 本文实例为大家分享了python实现抠图的具体代码,供大家参考,具体内容如下其中使用了opencv中的grabcut方法直接上代码# enc
- PHP中主要用strtr()和str_repalce()这两个函数替换字符串和数组,但你们都知道他们这两个函数的区别和用法吗?有不少文章在说
- 当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短
- 1. 基本使用remove() 函数可以删除列表中的指定元素语法list.remove( element )参数element:任意数据类型
- 1 集合集合可以使用大括号({})或者set()函数进行创建,但是创建一个空集合必须使用set()函数,而不能用{},大括号是用来创建一个空
- 本文实例讲述了Python常用字符串替换函数strip、replace及sub用法。分享给大家供大家参考,具体如下:今天在做一道今年秋季招聘
- python实现阶乘-基础版本什么是阶乘呢?在数学运算中n!表示n的阶乘,用数学公式表示为:n!=1*2*3*....*(n-1)*n下面提