Python-OpenCV图像边缘检测算法全解析

一.边缘检测

1.Canny 边缘检测

(1)概念

Canny边缘检测是图像处理中最著名,最常用的边缘检测算法之一,是1986年John F.Canny提出,一个最优的边缘检测器,满足三个标准

1.良好的检测性能,能够尽可能多的找出真是的边缘也就是低错误率。

2.良好的定位性能,检测到的边缘像素应该尽可能的接近真实边缘中心,即高定位精度。

3.清晰的响应,对于同一条边缘,算法只返回一个像素点,在最大限度上减少虚假响应。

(2)方法与解析

Canny 边缘检测是一个多阶段的算法,其流程如下图所示:

(3)使用

下面代码中简单使用了Canny边缘检测:

python 复制代码
import cv2

# 读取图像,为灰度
image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)
# 使用canny进行边缘检测
edges = cv2.Canny(image, threshold1=50, threshold2=100)

# 显示结果
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

其中有两个关键参数threshold1与threshold2,threshold1为低阈值,用于连接边缘,如果太高会漏掉弱边缘,如果太低会以引入过多噪声。threshold2为高阈值,如果太高会漏掉一些重要的边缘,如果太低会有过多噪声。在下图中左图为50:100右图为100:200。

观察图片发现左图有太多噪声,右图缺少边缘。这一点可以在图像处理过程中,先使用高斯滤波进行降噪再执行Canny边缘检测,能够显著提升边缘检测的质量。高斯滤波通过平滑图像有效抑制噪声干扰,避免噪声被误识别为边缘,使得后续Canny算子检测到的边缘更加准确和连续。这一预处理步骤尤其适用于噪声较多的图像,它能够在保留主要结构特征的同时减少虚假边缘,从而得到更清晰、更可靠的边缘检测结果。

代码:

python 复制代码
import cv2

# 读取图像
image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)

# 高斯滤波降噪
blurred_image = cv2.GaussianBlur(image, (5, 5), sigmaX=1.5)

# 使用 Canny 进行边缘检测
edges = cv2.Canny(blurred_image, threshold1=50, threshold2=100)

# 显示结果
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:

2.Sobel 算子

(1)概念

Sobel算子用于边缘检测的离散微分算子,通过计算图像亮度函数的灰度近似值来近似其梯度。其核心思想是一阶微分,卷积操作和梯度计算。

其中一阶微分是在图像边缘对应着图像函数的一阶导数的极值点;卷积操作是Sobel算子使用两个3*3的卷积核与原始图像进行平面卷积运算;梯度计算是通过两个方向的卷积结果,可以计算出每个像素点的梯度幅值和方向,梯度幅值越大说明该点越可能是边缘点。

(2)使用

下面的代码实现了以灰度模式读取test.png图像,然后分别计算x方向和y方向的Sobel梯度,通过平方和开方合并两个方向的梯度结果。代码将浮点型梯度数据转换为8位无符号整型以便显示,最后用Matplotlib并排展示原始图像、水平梯度、垂直梯度及综合梯度结果图,同时将三个梯度结果分别保存为PNG文件。整个过程展示了Sobel算子提取图像边缘特征的基本流程。

python 复制代码
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图片
image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)

# Sobel算子边缘检测
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)  # x方向
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)  # y方向
sobel_combined = np.sqrt(sobel_x**2 + sobel_y**2)      # 合并x和y方向

# 转换为8位无符号整型
sobel_x_abs = cv2.convertScaleAbs(sobel_x)
sobel_y_abs = cv2.convertScaleAbs(sobel_y)
sobel_combined_abs = cv2.convertScaleAbs(sobel_combined)

# 显示结果
plt.figure(figsize=(12, 6))

plt.subplot(2, 2, 1), plt.imshow(image, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 2), plt.imshow(sobel_x_abs, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 3), plt.imshow(sobel_y_abs, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 4), plt.imshow(sobel_combined_abs, cmap='gray')
plt.title('Sobel Combined'), plt.xticks([]), plt.yticks([])

plt.tight_layout()
plt.show()

# 保存结果
cv2.imwrite('sobel_x.png', sobel_x_abs)
cv2.imwrite('sobel_y.png', sobel_y_abs)
cv2.imwrite('sobel_combined.png', sobel_combined_abs)

3.Scharr 算子

(1)概念

Scharr算子是Sobel算子的改进版本,同样用于边缘检测的离散微分算子。它在计算图像梯度时使用了优化的卷积核,能够提供更好的旋转对称性和更高的精度,特别是在检测45度方向的边缘时表现更优。

(2)使用

下面的代码实现了以灰度模式读取test.png图像,然后分别计算x方向和y方向的Scharr梯度,通过平方和开方合并两个方向的梯度结果。代码将浮点型梯度数据转换为8位无符号整型以便显示,最后用Matplotlib并排展示原始图像、水平梯度、垂直梯度及综合梯度结果图,同时将三个梯度结果分别保存为PNG文件。整个过程展示了Scharr算子提取图像边缘特征的基本流程。

python 复制代码
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图片
image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)

# Scharr算子边缘检测
scharr_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)  # x方向
scharr_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)  # y方向
scharr_combined = np.sqrt(scharr_x**2 + scharr_y**2)  # 合并x和y方向

# 转换为8位无符号整型
scharr_x_abs = cv2.convertScaleAbs(scharr_x)
scharr_y_abs = cv2.convertScaleAbs(scharr_y)
scharr_combined_abs = cv2.convertScaleAbs(scharr_combined)

# 显示结果
plt.figure(figsize=(12, 6))

plt.subplot(2, 2, 1), plt.imshow(image, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 2), plt.imshow(scharr_x_abs, cmap='gray')
plt.title('Scharr X'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 3), plt.imshow(scharr_y_abs, cmap='gray')
plt.title('Scharr Y'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 4), plt.imshow(scharr_combined_abs, cmap='gray')
plt.title('Scharr Combined'), plt.xticks([]), plt.yticks([])

plt.tight_layout()
plt.show()

# 保存结果
cv2.imwrite('scharr_x.png', scharr_x_abs)
cv2.imwrite('scharr_y.png', scharr_y_abs)
cv2.imwrite('scharr_combined.png', scharr_combined_abs)

4.Laplacian 算子

(1)概念

Laplacian算子是一种基于二阶微分的边缘检测算子,通过计算图像的二阶导数来检测边缘。与Sobel和Scharr算子不同,Laplacian算子对图像中的灰度突变(如边缘、角点等)更加敏感,能够同时检测出边缘的位置和方向变化。

(2)使用

下面的代码实现了以灰度模式读取test.png图像,然后使用Laplacian算子计算二阶导数,并将结果转换为8位无符号整型以便显示。最后用Matplotlib展示原始图像和Laplacian边缘检测结果,同时保存Laplacian结果图。

python 复制代码
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图片
image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)

# Laplacian算子边缘检测
laplacian = cv2.Laplacian(image, cv2.CV_64F)  # 计算Laplacian

# 转换为8位无符号整型
laplacian_abs = cv2.convertScaleAbs(laplacian)

# 显示结果
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(image, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])

plt.subplot(1, 2, 2), plt.imshow(laplacian_abs, cmap='gray')
plt.title('Laplacian Edge Detection'), plt.xticks([]), plt.yticks([])

plt.tight_layout()
plt.show()

# 保存结果
cv2.imwrite('laplacian.png', laplacian_abs)
相关推荐
remaindertime2 小时前
基于Ollama和Spring AI:实现本地大模型对话与 RAG 功能
人工智能·后端·ai编程
y***54882 小时前
Vue语音识别开发
人工智能·语音识别
sdjnled2292 小时前
山东裸眼3D立体LED显示屏专业服务商
人工智能·3d
徒慕风流2 小时前
GeoSight:基于 Open3D 与 PySide6 的参数化 3D 模型处理与实时点云监控工具
计算机视觉·3d·信号处理
忘却的旋律dw3 小时前
使用LLM模型的tokenizer报错AttributeError: ‘dict‘ object has no attribute ‘model_type‘
人工智能·pytorch·python
学术小白人3 小时前
会议第一轮投稿!2026年物联网、数据科学与先进计算国际学术会议(IDSAC2026)
人工智能·物联网·数据分析·能源·制造·教育·rdlink研发家
极客BIM工作室3 小时前
用LLM+CadQuery自动生成CAD模型:CAD-Coder让文本秒变3D零件
人工智能·机器学习
苍何3 小时前
TRAE SOLO中国版终于来了,完全免费!
人工智能
苍何3 小时前
爆肝2天万字总结,飞书多维表格保姆级教程来了【建议收藏】
人工智能
非著名架构师3 小时前
极端天气下的供应链韧性:制造企业如何构建气象风险防御体系
大数据·人工智能·算法·制造·疾风气象大模型·风光功率预测