Opencv 学习笔记:基于图像变换 + 分水岭的图像分割(背景去除入门)

图像分割的核心是分离前景与背景,本文从 "手动背景去除" 入手,结合基础图像变换,为分水岭算法分割打下基础,新手可快速掌握背景像素过滤的核心逻辑。

核心代码实现

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

# 1. 读取图像并校验
src = cv.imread('./image/28.bmp')
if src is None:
    print('图像读取失败,请检查路径!')
    exit()

# 备份原图(避免后续操作修改原始数据)
src_origin = src.copy()
# 初始化结果画布
result = np.zeros_like(src)

# 2. 手动背景去除:过滤白色背景(RGB=255,255,255)
# 遍历图像所有像素(优化双层循环,避免冗余自增)
for i in range(src.shape[0]):
    for j in range(src.shape[1]):
        # 获取当前像素的BGR值
        b, g, r = src[i, j]
        # 判断是否为白色背景像素
        if b == 255 and g == 255 and r == 255:
            src[i, j] = [0, 0, 0]  # 白色背景转为黑色
        else:
            result[i, j] = src[i, j]  # 保留前景像素

# 3. 分水岭算法前置处理(可选,进阶分割)
gray = cv.cvtColor(result, cv.COLOR_BGR2GRAY)
# 二值化:强化前景与背景对比
ret, binary = cv.threshold(gray, 10, 255, cv.THRESH_BINARY)
# 距离变换:获取前景种子点
dist_transform = cv.distanceTransform(binary, cv.DIST_L2, 5)
ret, sure_fg = cv.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
# 查找未知区域(背景-前景)
sure_bg = cv.dilate(binary, np.ones((3,3), np.uint8), iterations=2)
unknown = cv.subtract(sure_bg, sure_fg)

# 4. 标记连通域,执行分水岭分割
ret, markers = cv.connectedComponents(sure_fg)
markers = markers + 1  # 背景标记为1,避免与未知区域混淆
markers[unknown==255] = 0  # 未知区域标记为0
markers = cv.watershed(src_origin, markers)
src_origin[markers == -1] = [0, 0, 255]  # 分割线标红

# 5. 显示结果
cv.namedWindow('背景去除结果', cv.WINDOW_NORMAL)
cv.resizeWindow('背景去除结果', 600, 600)
cv.imshow('背景去除结果', result)

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

cv.waitKeyEx(0)
cv.destroyAllWindows()

关键知识点解析

1. 手动背景去除核心

步骤 核心逻辑 优化要点
像素遍历 双层循环遍历src.shape[0](高)和src.shape[1](宽) 原代码冗余j=j+1会导致列索引跳步,直接遍历 range 即可
背景判断 b==255 and g==255 and r==255 OpenCV 中像素为 BGR 顺序,需按蓝、绿、红判断
背景替换 白色背景→黑色[0,0,0] 保留前景像素到新画布,避免修改原图后无法追溯

2. 分水岭算法核心流程

步骤 核心 API 作用说明
距离变换 cv.distanceTransform() 计算前景像素到背景的距离,精准定位前景核心区域
前景 / 背景标记 cv.connectedComponents() 标记确定的前景 / 背景,避免分割过度
分水岭分割 cv.watershed() 基于标记的图像分割,markers==-1为分割边界
分割线标注 红色[0,0,255] 直观展示分割边界,验证分割效果

3. 原代码核心修复

  • 索引跳步问题 :原代码j = j+1导致列索引每次循环自增两次,漏检一半像素,直接删除该冗余代码;
  • 画布初始化 :新增src_origin = src.copy()备份原图,避免背景去除操作影响分水岭分割;
  • 效率优化:合并像素判断与赋值逻辑,减少重复操作,提升遍历速度;
  • 鲁棒性增强:增加图像读取校验,避免空图像导致后续报错。

总结

  1. 手动背景去除的核心是遍历像素 + RGB 值判断,需注意 OpenCV 的 BGR 像素顺序,避免索引跳步;
  2. 分水岭算法分割的关键是标记确定的前景 / 背景,距离变换可精准定位前景种子点;
  3. 背景去除是分水岭分割的基础预处理,可大幅提升分割准确率,适配白色背景的目标分割场景。
相关推荐
Wilber的技术分享16 分钟前
【LeetCode高频手撕题 2】面试中常见的手撕算法题(小红书)
笔记·算法·leetcode·面试
愚昧之山绝望之谷开悟之坡44 分钟前
合格境外投资者
笔记
寒秋花开曾相惜3 小时前
(学习笔记)3.8 指针运算(3.8.3 嵌套的数组& 3.8.4 定长数组)
java·开发语言·笔记·学习·算法
movigo7_dou3 小时前
双目立体匹配
数码相机·opencv·计算机视觉
是翔仔呐3 小时前
第11章 显示外设驱动:I2C协议OLED屏、SPI协议LCD屏字符/图片/中文显示
c语言·开发语言·stm32·单片机·嵌入式硬件·学习·gitee
_李小白3 小时前
【AI大模型学习笔记之平台篇】第五篇:Trae常用模型介绍与性能对比
人工智能·笔记·学习
承渊政道4 小时前
【优选算法】(实战体会位运算的逻辑思维)
数据结构·c++·笔记·学习·算法·leetcode·visual studio
AI-Ming4 小时前
程序员转行学习 AI 大模型: 踩坑记录:服务器内存不够,程序被killed
服务器·人工智能·python·gpt·深度学习·学习·agi
m0_716765234 小时前
C++提高编程--STL常用容器(set/multiset、map/multimap容器)详解
java·开发语言·c++·经验分享·学习·青少年编程·visual studio
2501_945318494 小时前
零基础学习AI的选型指南:CAIE认证与编程型AI认证如何取舍
人工智能·学习