Opencv 学习笔记:腐蚀操作 + 轮廓标记 + 分水岭分割

腐蚀是形态学操作的核心,常与轮廓分析、分水岭算法结合实现图像分割。本文整合「腐蚀去噪→轮廓标记→分水岭分割」全流程,演示从预处理到最终分割的完整逻辑,新手可直接复用。

核心代码实现

python 复制代码
import cv2 as cv
import numpy as np

# 1. 读取图像并初始化(补充完整流程)
src = cv.imread('./image/test.bmp')  # 替换为你的图像路径
if src is None:
    print('图像读取失败,请检查路径!')
    exit()
srcss = src.copy()  # 分水岭分割画布
result4 = src.copy()  # 腐蚀输入图像(需为单通道二值图,此处补充预处理)

# 预处理:转为灰度图→二值化(腐蚀操作的前提)
gray = cv.cvtColor(result4, cv.COLOR_BGR2GRAY)
ret, result4 = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)

# 2. 腐蚀操作(核心:去除小噪点,强化前景轮廓)
# 创建结构化元素:9×9矩形核(尺寸越大,腐蚀越强)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (9, 9))
result5 = cv.erode(result4, kernel)  # 执行腐蚀

# 3. 轮廓检测(基于腐蚀后的图像)
result6 = np.uint8(result5)  # 确保为uint8格式(轮廓检测要求)
contours, hierarchy = cv.findContours(result6, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)

# 4. 轮廓标记(为分水岭算法生成标记图)
# 初始化标记图:float32类型,尺寸与原图一致
result7 = np.zeros((src.shape[0], src.shape[1]), np.float32)
# 遍历轮廓,为每个轮廓分配唯一标记值(从5开始,避免与背景冲突)
for i, contour in enumerate(contours):
    cv.drawContours(result7, contours, i, i+5, 1)  # 标记值=i+5,线宽1

# 5. 执行分水岭分割
cv.watershed(srcss, result7)
# 标注分割边界(标记值为-1的区域是分割线)
srcss[result7 == -1] = [0, 0, 255]  # 分割线标红

# 6. 显示结果
cv.namedWindow('腐蚀结果', cv.WINDOW_NORMAL)
cv.resizeWindow('腐蚀结果', 600, 600)
cv.imshow('腐蚀结果', result5)

cv.namedWindow('轮廓标记图', cv.WINDOW_NORMAL)
cv.resizeWindow('轮廓标记图', 600, 600)
cv.imshow('轮廓标记图', result7 / result7.max() * 255)  # 归一化显示

cv.namedWindow('分水岭分割结果', cv.WINDOW_NORMAL)
cv.resizeWindow('分水岭分割结果', 600, 600)
cv.imshow('分水岭分割结果', srcss)

cv.waitKeyEx(0)
cv.destroyAllWindows()

关键知识点解析

1. 核心流程拆解

步骤 核心 API 作用说明
腐蚀操作 cv.erode() 用 9×9 矩形核腐蚀图像,消除小噪点,让前景轮廓更清晰
轮廓检测 cv.findContours() 提取腐蚀后图像的轮廓,为分水岭提供前景标记
轮廓标记 cv.drawContours() 为每个轮廓分配唯一数值标记(i+5),生成分水岭标记图
分水岭分割 cv.watershed() 基于标记图分割图像,result7 == -1为分割边界

2. 核心参数与避坑点

  • 腐蚀核参数cv.getStructuringElement(cv.MORPH_RECT, (9,9)):矩形核尺寸越大,腐蚀效果越强,需根据图像噪点大小调整(小噪点用 3×3,大噪点用 9×9);
  • 轮廓标记值:标记值从 5 开始(而非 0/1),避免与分水岭算法的「背景(0)」「未知区域(1)」冲突,是分割成功的关键;
  • 数据类型要求
    • 轮廓检测输入必须为uint8类型,因此需result6 = np.uint8(result5)
    • 分水岭标记图必须为float32类型,因此初始化result7时指定np.float32
  • 分割边界标注watershed执行后,标记图中值为-1的像素是分割边界,用红色标注可直观验证分割效果。

3. 形态学操作扩展

操作 API 作用
膨胀 cv.dilate() 与腐蚀相反,扩大前景区域,修复轮廓断裂
开运算 cv.morphologyEx(src, cv.MORPH_OPEN, kernel) 先腐蚀后膨胀,去除小噪点且不改变前景大小
闭运算 cv.morphologyEx(src, cv.MORPH_CLOSE, kernel) 先膨胀后腐蚀,填充前景孔洞

总结

  1. 腐蚀操作是分水岭分割的关键预处理,核心作用是去除小噪点、强化前景轮廓,核尺寸需适配噪点大小;
  2. 分水岭算法的核心是「标记图」:轮廓标记值需避开 0/1,避免与背景 / 未知区域冲突;
  3. 数据类型严格匹配(轮廓检测→uint8,分水岭标记图→float32)是流程运行的基础。
相关推荐
saoys1 小时前
Opencv 学习笔记:距离变换(DIST_L1 算法实战 + 归一化)
笔记·opencv·学习
宵时待雨2 小时前
C++笔记归纳2:类和对象
c++·笔记
在这habit之下2 小时前
Tomcat学习总结
学习
尘似鹤2 小时前
linux驱动学习---竞争与并发(原子操作与各种锁)
linux·学习
在这habit之下2 小时前
HAProxy学习总结
学习
来两个炸鸡腿2 小时前
【Datawhale组队学习202602】Hello-Agents task06 框架应用开发实战
人工智能·学习·大模型·智能体
盐焗西兰花2 小时前
鸿蒙学习实战之路-STG系列(4/11)-应用选择页功能详解
服务器·学习·harmonyos
稻草猫.2 小时前
TCP与UDP:传输层协议深度解析
笔记·后端·网络协议