基于边缘的图像分割,核心思路是先检测出图像中物体的边界,再利用这些边界把图像划分为不同的区域。下面我为你梳理最常用的流程和代码实现,所有示例都基于 OpenCV 和 Python。
典型的“边缘分割”遵循以下步骤:
预处理:转灰度图、滤波去噪(高斯/中值/双边滤波)。
边缘检测:用 Canny、Sobel 等算子得到边界图。
边缘完善(可选):通过形态学操作(闭运算、膨胀)把断裂的边缘连接起来。
区域形成:在边缘图上寻找闭合轮廓,填充轮廓形成分割区域;或者用分水岭算法直接以边缘梯度作为输入。
这种方法适合目标与背景对比明显,且边缘能形成闭合轮廓的场景。
代码如下:
import cv2
import numpy as np
# 1. 读取图像
img = cv2.imread('./images/car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 去噪(双边滤波在保边的同时去噪效果更好)
blur = cv2.bilateralFilter(gray, 9, 75, 75)
# 3. Canny 边缘检测
edges = cv2.Canny(blur, 50, 150)
# 4. 形态学闭运算:连接细小断裂,使轮廓闭合
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel, iterations=2)
# 5. 寻找轮廓(只找外轮廓,且只保留有层级关系的)
contours, hierarchy = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 6. 绘制分割结果:为每个轮廓区域填充不同颜色
segmented = np.zeros_like(img)
for i, cnt in enumerate(contours):
# 滤除太小的噪点区域
if cv2.contourArea(cnt) < 500:
continue
# 随机颜色填充
color = np.random.randint(0, 255, 3).tolist()
cv2.drawContours(segmented, [cnt], -1, color, thickness=cv2.FILLED)
# 查看结果
cv2.imshow('Edges', edges)
cv2.imshow('Closed', closed)
cv2.imshow('Segmented', segmented)
cv2.waitKey(0)
效果图展示如下:

全部评论