当前位置:首页>python>一起来用OpenCV-Python搞图像图像轮廓提取 | Part.6

一起来用OpenCV-Python搞图像图像轮廓提取 | Part.6

  • 2026-10-11 07:33:02
一起来用OpenCV-Python搞图像图像轮廓提取 | Part.6

第6篇|OpenCV边缘检测✂️捕捉目标轮廓

上一篇我们讲解了阈值处理,实现了目标与背景的分离,这是图像识别的基础。

但要真正“识别”一个目标,需要捕捉它的边缘——边缘是目标与背景的分界线,也是目标形状、轮廓的关键特征(比如人脸的轮廓、文字的笔画边缘、物体的轮廓)。

今天我们就来讲讲OpenCV中最核心的边缘检测技术。

📌 什么是边缘?如何检测边缘?

首先我们明白一个核心概念:图像中的“边缘”,本质是像素值发生剧烈变化的区域。

比如一张黑色背景上的白色方块,方块的边缘处,像素值从0(黑色)瞬间变为255(白色),这种剧烈的灰度变化,就是边缘的特征。

边缘检测的逻辑,就是识别出像素值迅速变化的区域,具体大概两步:

  1. 降噪处理: 图像中通常存在噪声(比如轻微的杂点),噪声会导致边缘误检测,因此第一步需要对图像进行模糊降噪,让真实边缘更加明显;

  2. 边缘检测: 通过算法计算像素值的变化幅度,或说梯度。梯度越大,说明像素值变化越剧烈,越可能是边缘,再通过设定阈值,保留梯度大的区域,即得到了边缘。

OpenCV提供了多种常用的边缘检测算法,适用于不同场景,我们重点讲解最常用的Canny算法,以及Sobel、Laplacian两种补充算法。

🔧 三种常用边缘检测算法

我们以“物体轮廓图像”为例,分别演示三种算法的边缘检测效果。

1. Canny边缘检测

Canny算法是目前最常用的边缘检测算法,抗噪声能力强,检测出的边缘更细腻、更精准。它能有效去除虚假边缘,保留真实边缘,适用于大多数场景。

函数调用:

cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)

参数(重点在前3个):

  • image: 需要检测的图像矩阵(灰度图最佳,彩色图也可);

  • threshold1: 低阈值(用于过滤弱边缘,常用50-100);

  • threshold2: 高阈值(用于确定强边缘,常用100-200);

  • 补充:高阈值和低阈值的比例通常为2:1或3:1,高于高阈值的是强边缘,低于低阈值的是弱边缘,介于两者之间的,若与强边缘相连,则保留,否则去除。

import cv2# 读取图像并转换为灰度图img = cv2.imread("test.png")img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 高斯模糊降噪(Canny算法内置降噪,但额外降噪效果通常能更好)img_blur = cv2.GaussianBlur(img_gray, (3, 3), 0)  # (3,3)是模糊核大小# Canny边缘检测(低阈值50,高阈值100)canny_edges = cv2.Canny(img_blur, 50, 100)cv2.imshow("original", img)cv2.imshow("Canny edges", canny_edges)cv2.waitKey(0)cv2.destroyAllWindows()

2. Sobel边缘检测

Sobel算法的核心是“通过梯度计算,分别检测水平方向和垂直方向的边缘”,抗噪声能力强,计算速度快,但检测出的边缘较粗,不够细腻,适合对边缘精度要求不高的场景。

函数调用:

cv2.Sobel(src, ddepth, dx, dy, ksize)

参数说明:

  • src:灰度图像矩阵;

  • ddepth:输出图像的深度(通常设为cv2.CV_64F,避免梯度计算时数字溢出);

  • dx:水平方向梯度(1表示检测水平边缘,0表示不检测);

  • dy:垂直方向梯度(1表示检测垂直边缘,0表示不检测);

  • ksize: Sobel核的大小(常用3、5、7,值越大,则边缘越粗)。

import cv2import numpy as npimport matplotlib.pyplot as pltimg = cv2.imread("test.png")img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 检测水平方向边缘(dx=1,dy=0)sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)# 检测垂直方向边缘(dx=0,dy=1)sobel_y = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)# 处理梯度负值(将负值转为正值,避免边缘丢失)sobel_x = cv2.convertScaleAbs(sobel_x)sobel_y = cv2.convertScaleAbs(sobel_y)# 合并水平和垂直边缘sobel_edges = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)plt.subplot(2, 2, 1)plt.imshow(img_gray, cmap="gray")plt.title("Original Gray")plt.subplot(2, 2, 2)plt.imshow(sobel_x, cmap="gray")plt.title("Horizontal Edge")plt.subplot(2, 2, 3)plt.imshow(sobel_y, cmap="gray")plt.title("Vertical Edge")plt.subplot(2, 2, 4)plt.imshow(sobel_edges, cmap="gray")plt.title("Sobel Combined Edge")plt.show()

3. Laplacian边缘检测

Laplacian算法是“检测所有方向的边缘”(不需要分别检测水平和垂直),检测速度快,但抗噪声能力弱,容易检测出虚假边缘,适合“噪声少、边缘清晰”的场景。

函数调用:

cv2.Laplacian(src, ddepth, ksize)

参数说明:与Sobel算法类似,ddepth设为cv2.CV_64F,ksize为奇数(3、5、7)。

import cv2import numpy as npimg = cv2.imread("test.png")img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 高斯模糊降噪(Laplacian抗噪声弱,须先降噪)img_blur = cv2.GaussianBlur(img_gray, (3, 3), 0)# Laplacian边缘检测laplacian_edges = cv2.Laplacian(img_blur, cv2.CV_64F, ksize=3)# 处理梯度负值,转为正值laplacian_edges = cv2.convertScaleAbs(laplacian_edges)cv2.imshow("Original Image", img)cv2.imshow("Laplacian Edge Detection", laplacian_edges)cv2.waitKey(0)cv2.destroyAllWindows()

📊 三种算法对比

  • Canny算法:效果最好、抗噪声强、边缘细腻,适合大多数场景(首选);

  • Sobel算法:抗噪声强、速度快、边缘较粗,适合粗轮廓检测、工业场景;

  • Laplacian算法:检测所有方向边缘、速度快,抗噪声弱,适合噪声少、简单场景。

💡 小贴士

  • 边缘模糊问题 先做高斯模糊降噪,尤其是Laplacian算法,降噪很关键。

  • Canny算法阈值选择 低阈值和高阈值比例2:1或3:1;若边缘太少,降低低阈值;若虚假边缘太多,提高高阈值。

📌 小结+预告

本篇我们介绍了三种常用的边缘检测算法——Canny、Sobel、Laplacian,了解了算法的原理、优缺点和适用场景。

下篇我们将学习“轮廓检测与形状分析”,基于边缘检测的结果,提取目标的完整轮廓,再通过轮廓分析,判断目标的形状(比如圆形、矩形、三角形)、计算轮廓的面积和周长等等。


往期回顾:

字符串str的操作|Python自学成才(番外篇1)

用OpenCV提取图像中的目标区域 | Part.5

OpenCV在处理图像时的颜色异常问题 | Part.4

改个文件的后缀名,然后在文件里藏点好东西

你知不知道计算机是如何识别一个文件的类型

用OpenCV对图片进行简单的几何操作 | OpenCV-Part.3

最新文章

随机文章