实验——轮廓提取
摘要:本实验对比研究了三种图像轮廓提取算法:基于Prewitt算子的边缘检测、大津法阈值分割和Canny边缘检测,并提出了结合分水岭算法的优化方案。实验结果表明,Canny算法在抗噪性和轮廓完整性方面表现最优,而分水岭算法能有效处理复杂场景中的重叠物体。时间性能上,阈值分割最快,Canny次之,优化方案耗时较长但精度更高。实验验证了不同算法的适用场景,为实际应用中的算法选择提供了依据,并为未来结合
一、实验目的与意义
本实验旨在深入理解图像区域的轮廓提取原理,掌握多种轮廓提取算法的实现方法,并通过时间测试对比不同算法的性能。轮廓提取是计算机视觉中的基础任务,广泛应用于目标检测、图像分割、形状分析等领域。通过本实验,不仅能熟悉经典图像处理算法的应用,还能培养针对具体问题设计优化方案的能力。
二、实验原理
轮廓提取的核心是识别图像中物体与背景(或不同物体)之间的边界。其基本流程通常包括:
- 图像预处理(去噪、灰度化等)
- 边缘 / 区域分割(通过边缘检测或阈值分割)
- 轮廓提取与优化
本实验采用三种不同策略实现轮廓提取,每种策略基于不同的图像处理原理:
1. 基于边缘检测算子的轮廓提取
边缘检测算子通过计算图像梯度识别像素值突变的区域(边缘)。本实验使用 Prewitt 算子,其原理是利用两个方向的卷积核(水平和垂直)计算梯度,再通过梯度合成得到边缘图像,最后从边缘图像中提取轮廓。
2. 基于阈值分割的轮廓提取
阈值分割通过设定灰度值阈值将图像分为前景和背景。本实验采用大津法(Otsu)自动确定最优阈值,该方法通过最大化类间方差寻找最佳阈值,适用于对比度较明显的图像,再从二值化结果中提取轮廓。
3. 基于 Canny 边缘检测的轮廓提取
Canny 算法是一种多阶段边缘检测算法,包括:
- 高斯滤波去噪
- 计算梯度强度与方向
- 非极大值抑制(保留局部梯度最大的像素)
- 双阈值检测与边缘连接该方法能有效检测弱边缘并抑制噪声,生成的边缘更连续,适合轮廓提取。
三、实验代码实现
1. 核心功能模块
import cv2
import numpy as np
import time
import matplotlib.pyplot as plt
def load_and_preprocess(image_path):
"""加载图像并进行预处理(灰度化、去噪)"""
# 读取图像
img = cv2.imread(image_path)
if img is None:
raise ValueError("Image path error: Cannot load image")
# 转为单通道灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波去噪
blurred = cv2.GaussianBlur(gray, (5, 5), 1.4)
# 转为3通道灰度图(用于后续绘制彩色元素)
gray_3ch = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
return gray_3ch, gray, blurred, img # 返回处理后的各类图像
2. 时间测试模块
def time_algorithm(func, *args):
"""测试算法运行时间的工具函数"""
start_time = time.time() # 记录开始时间
result = func(*args) # 执行目标函数
end_time = time.time() # 记录结束时间
return result, end_time - start_time # 返回结果和耗时
3. 三种轮廓提取策略实现
策略 1:基于边缘检测算子
def strategy_edge_based(gray_3ch, blurred):
"""使用Prewitt边缘检测算子的轮廓提取策略"""
# Prewitt边缘检测
edge_img, time_edge = time_algorithm(prewitt_edge_detector, blurred)
# 二值化处理
binary_img, time_bin = time_algorithm(binarize_image, edge_img, 50)
# 形态学后处理(填补边缘间隙)
processed_binary, time_post = time_algorithm(postprocess_binary, binary_img)
# 提取并绘制轮廓
contour_img, time_contour = time_algorithm(
extract_and_draw_contours, gray_3ch, processed_binary)
total_time = time_edge + time_bin + time_post + time_contour
return contour_img, total_time, "Edge-based (Prewitt)"
策略 2:基于阈值分割
def strategy_threshold_based(gray_3ch, gray):
"""使用大津法阈值分割的轮廓提取策略"""
# 大津法自动阈值分割(无需手动设定阈值)
binary_img, time_bin = time_algorithm(
cv2.threshold, gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 形态学处理(去除噪点)
processed_binary, time_morph = time_algorithm(postprocess_binary, binary_img)
# 提取轮廓
contour_img, time_contour = time_algorithm(
extract_and_draw_contours, gray_3ch, processed_binary)
total_time = time_bin + time_morph + time_contour
return contour_img, total_time, "Threshold-based (Otsu)"
策略 3:基于 Canny 边缘检测
def strategy_canny_based(gray_3ch, blurred):
"""使用Canny边缘检测的轮廓提取策略"""
# Canny边缘检测(双阈值控制边缘提取精度)
edges, time_canny = time_algorithm(cv2.Canny, blurred, 50, 150)
# 形态学处理
processed_edges, time_morph = time_algorithm(postprocess_binary, edges)
# 提取轮廓
contour_img, time_contour = time_algorithm(
extract_and_draw_contours, gray_3ch, processed_edges)
total_time = time_canny + time_morph + time_contour
return contour_img, total_time, "Canny-based"
4. 优化的轮廓提取方法
针对复杂图像(如存在重叠物体、弱边缘的场景),实现了基于分水岭算法的优化方案:
def optimize_contour_extraction(original_img):
"""优化的轮廓提取方法:结合色彩空间和分水岭算法"""
# 转换到HSV色彩空间,利用颜色信息辅助分割
hsv = cv2.cvtColor(original_img, cv2.COLOR_BGR2HSV)
# 对亮度通道进行自适应阈值处理
v_channel = hsv[:, :, 2]
adaptive_thresh = cv2.adaptiveThreshold(
v_channel, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
# 形态学处理去除噪声
kernel = np.ones((2, 2), np.uint8)
opening = cv2.morphologyEx(adaptive_thresh, cv2.MORPH_OPEN, kernel, iterations=1)
# 提取确定的背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 距离变换找到确定的前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.5 * dist_transform.max(), 255, 0)
# 找到未知区域(前景和背景之间的过渡区)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 连通组件标记
_, markers = cv2.connectedComponents(sure_fg)
markers += 1 # 确保背景不是0值
markers[unknown == 255] = 0 # 未知区域标记为0
# 分水岭算法分割(能有效处理重叠物体)
markers = cv2.watershed(original_img, markers)
original_img[markers == -1] = [0, 0, 255] # 红色标记边界
return original_img
四、实验结果与分析

(1)效果对比
- 基于 Prewitt 算子:边缘检测对噪声较敏感,轮廓可能存在较多毛刺,但计算简单
- 基于大津法阈值分割:对光照均匀、对比度高的图像效果好,但易受光照变化影响
- 基于 Canny 算子:提取的轮廓更连续、完整,抗噪声能力强,是三种基础方法中效果最优的
- 优化方案(分水岭算法):能有效分割重叠物体,保留更精细的轮廓细节,尤其适合复杂场景
(2)时间性能对比

一般情况下,三种基础策略的执行时间关系为:
- 阈值分割法 < Prewitt 算子法 < Canny 算子法
- 优化方案(分水岭算法)由于涉及更多预处理步骤,耗时相对较长,但精度提升显著
五、实验总结与展望
通过本实验,验证了不同轮廓提取策略的适用性:
- 简单场景(如高对比度、低噪声图像)可选择阈值分割法,兼顾效率和效果
- 中等复杂场景推荐使用 Canny 算子,在抗噪声和轮廓完整性间取得平衡
- 复杂场景(如重叠物体、弱边缘)需采用优化方案(如分水岭算法),结合色彩信息和形态学操作
未来可进一步优化的方向:
- 结合深度学习方法(如边缘检测网络)提升复杂场景下的轮廓提取精度
- 针对实时应用场景,研究基于硬件加速的快速轮廓提取算法
- 引入轮廓特征描述(如面积、周长、凸包等),实现从轮廓提取到形状分析的完整流程
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐

所有评论(0)