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)

结果如下:

Python利用OpenCV和skimage实现图像边缘检测

Python利用OpenCV和skimage实现图像边缘检测

三、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()

结果如下:

Python利用OpenCV和skimage实现图像边缘检测

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()

结果如下:

Python利用OpenCV和skimage实现图像边缘检测

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

标签:Python,OpenCV,skimage,图像,边缘,检测
0
投稿

猜你喜欢

  • python中文乱码的解决方法

    2022-07-12 18:03:48
  • layui表单提交到后台自动封装到实体类的方法

    2024-04-22 22:33:11
  • 用 SQL 脚本将 Access 导入 MSSQL 2000/2005 方法

    2008-10-22 13:51:00
  • Python列表(list)、字典(dict)、字符串(string)基本操作小结

    2023-03-02 01:33:01
  • numpy之多维数组的创建全过程

    2023-06-22 03:58:03
  • ASP中正则表达式的应用

    2010-05-27 12:24:00
  • SQL2005 学习笔记 窗口函数(OVER)

    2024-01-27 09:50:49
  • 详解使用 pyenv 管理多个版本 python 环境

    2023-11-01 03:40:05
  • SQL Server格式转换函数Cast、Convert介绍

    2024-01-22 18:42:16
  • PHP实现向关联数组指定的Key之前插入元素的方法

    2023-07-14 08:41:33
  • 怎么解决pycharm license Acti的方法

    2022-12-27 10:36:39
  • 让设计散发文化韵味

    2009-03-22 15:01:00
  • python统计mysql数据量变化并调用接口告警的示例代码

    2024-01-22 22:15:13
  • Golang 高效排序数据详情

    2023-06-23 08:23:41
  • Python绘制牛奶冻曲线(高木曲线)案例

    2022-04-05 16:35:08
  • Python函数实现学员管理系统

    2023-06-22 03:32:30
  • python实现邮箱发送信息

    2023-02-25 15:11:51
  • python读取html中指定元素生成excle文件示例

    2021-04-08 19:51:11
  • Python 中pandas索引切片读取数据缺失数据处理问题

    2021-06-02 05:13:28
  • 详解Open Folder as PyCharm Project怎么添加的方法

    2021-06-25 05:56:53
  • asp之家 网络编程 m.aspxhome.com