OpenCV基于边缘的图片分割

14人浏览 / 0人评论 / 添加收藏

基于边缘的图像分割,核心思路是先检测出图像中物体的边界,再利用这些边界把图像划分为不同的区域。下面我为你梳理最常用的流程和代码实现,所有示例都基于 OpenCV 和 Python。

一、基本原理

典型的“边缘分割”遵循以下步骤:

预处理:转灰度图、滤波去噪(高斯/中值/双边滤波)。

边缘检测:用 Canny、Sobel 等算子得到边界图。

边缘完善(可选):通过形态学操作(闭运算、膨胀)把断裂的边缘连接起来。

区域形成:在边缘图上寻找闭合轮廓,填充轮廓形成分割区域;或者用分水岭算法直接以边缘梯度作为输入。

二、方法:Canny + 轮廓填充(直观、常用)

这种方法适合目标与背景对比明显,且边缘能形成闭合轮廓的场景。

代码如下:

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)

效果图展示如下:

全部评论