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)
相关推荐
格林威2 小时前
机器视觉选Halcon还是OpenCV?
人工智能·数码相机·opencv·yolo·计算机视觉·视觉检测·制造
ISACA中国3 小时前
《第四届数字信任大会》精彩观点:腾讯经验-人工智能安全风险之应对与实践|从十大风险到企业级防护架构
人工智能·安全·架构·漏洞案例·大模型越狱·企业级防护
James. 常德 student3 小时前
华为 ai 机考 编程题解答
java·人工智能·华为
居然JuRan3 小时前
Qwen3-8B vLLM 部署调用
人工智能
GIS数据转换器4 小时前
2025无人机在低空物流中的应用实践
大数据·网络·人工智能·安全·无人机
云卓SKYDROID4 小时前
无人机台风天通信技术要点
人工智能·无人机·航电系统·高科技·云卓科技
致Great4 小时前
AI Agent的四象限法则:解码智能体应用的底层逻辑
人工智能·大模型·agent·智能体·deepresearch
余衫马4 小时前
大模型实战:通义万相2.1-文生视频-1.3B
人工智能·大模型·文生视频
阿里云大数据AI技术4 小时前
云上AI推理平台全掌握(6):大规模EP专家并行
人工智能