首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

opencv进阶学习笔记14:分水岭算法 实现图像分割

  • 23-09-22 21:02
  • 3833
  • 12193
blog.csdn.net

基础版学习笔记目录:
python3+opencv学习笔记汇总目录(适合基础入门学习)
进阶版笔记目录链接:
python+opencv进阶版学习笔记目录(适合有一定基础)

分水岭算法原理

分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特征。
其他图像分割方法,如阈值,边缘检测等都不会考虑像素在空间关系上的相似性和封闭性这一概念,彼此像素间互相独立,没有统一性。分水岭算法较其他分割方法更具有思想性,更符合人眼对图像的印象。

任意的灰度图像可以被看做是地质学表面,高亮度的地方是山峰,低亮度的地方是山谷。给每个孤立的山谷(局部最小值)不同颜色的水(标签),当水涨起来,根据周围的山峰(梯度),不同的山谷也就是不同的颜色会开始合并,要避免这个,你可以在水要合并的地方建立障碍,直到所有山峰都被淹没。你所创建的障碍就是分割结果,这个就是分水岭的原理,但是这个方法会分割过度,因为有噪点,或者其他图像上的错误。所以OpenCV实现了一个基于掩模的分水岭算法,你可以指定哪些是要合并的点,哪些不是,这是一个交互式的图像分割,我们要做的是给不同的标签。给我们知道是前景或者是目标用一种颜色加上标签,给我们知道是背景或者非目标加上另一个颜色,最后不知道是什么的区域标记为0. 然后使用分水岭算法。

距离变换

先将图像进行距离变换使出现山峰和山谷

API实现

1图像二值化

import cv2 as cv
import numpy as np

def watershed_demo():
    # remove noise if any
    print(src.shape)#图像维度(348, 500, 3)
    blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#边缘保留滤波去噪
    # grayinary image
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#转换为灰度图
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化
    cv.imshow("binary-image", binary)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("coins.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
watershed_demo()
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2形态学操作

import cv2 as cv
import numpy as np

def watershed_demo():
    # remove noise if any
    print(src.shape)#图像维度(348, 500, 3)
    blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移滤波去噪
    # grayinary image
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#转换为灰度图
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化
    #cv.imshow("binary-image", binary)
    # 形态学变换
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷积核
    mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#开运算
    sure_bg = cv.dilate(mb, kernel, iterations=3)#对开运算结果膨胀
    cv.imshow("mor-opt", sure_bg)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("coins.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
watershed_demo()
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3对开运算结果进行距离变换
先不管膨胀结果,对开运算结果进行距离计算

def distanceTransform(src, distanceType, maskSize, dst=None, dstType=None)
  • 1

src:输入的图像,一般为二值图像
distanceType:所用的求解距离的类型(CV_DIST_L1, CV_DIST_L2 , CV_DIST_C)
maskSize:距离变换掩模的大小

我们需要对distanceTransform返回的结果进行归一化处理,使用normalize

import cv2 as cv
import numpy as np

def watershed_demo():
    # remove noise if any
    print(src.shape)#图像维度(348, 500, 3)
    blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移滤波去噪
    # grayinary image
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#转换为灰度图
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化
    #cv.imshow("binary-image", binary)

    # m形态学操作
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷积核
    mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#开运算
    sure_bg = cv.dilate(mb, kernel, iterations=3)#对开运算结果膨胀
    #cv.imshow("mor-opt", sure_bg)

    # 对开运算结果距离变换
    dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
    dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    cv.imshow("distance-t", dist_output * 50)

print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("coins.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
watershed_demo()
cv.waitKey(0)

cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

4生成种子

import cv2 as cv
import numpy as np

def watershed_demo():
    # remove noise if any
    print(src.shape)#图像维度(348, 500, 3)
    blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移滤波去噪
    # grayinary image
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#转换为灰度图
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化
    #cv.imshow("binary-image", binary)

    # m形态学操作
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷积核
    mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#开运算
    sure_bg = cv.dilate(mb, kernel, iterations=3)#对开运算结果膨胀
    #cv.imshow("mor-opt", sure_bg)

    # 对开运算结果距离变换
    dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
    dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    #cv.imshow("distance-t", dist_output * 50)


    ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)

    surface_fg = np.uint8(surface)
    cv.imshow("surface-bin", surface_fg)#种子

print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("coins.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
watershed_demo()
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

5生成marker和分水岭变换

import cv2 as cv
import numpy as np

def watershed_demo():
    # remove noise if any
    print(src.shape)#图像维度(348, 500, 3)
    blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移滤波去噪
    # grayinary image
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#转换为灰度图
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化
    #cv.imshow("binary-image", binary)

    # m形态学操作
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷积核
    mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#开运算
    sure_bg = cv.dilate(mb, kernel, iterations=3)#对开运算结果膨胀
    #cv.imshow("mor-opt", sure_bg)

    # 对开运算结果距离变换
    dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
    dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    #cv.imshow("distance-t", dist_output * 50)


    ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)

    surface_fg = np.uint8(surface)
    #cv.imshow("surface-bin", surface_fg)#种子

    unknown = cv.subtract(sure_bg, surface_fg)#种子区域除外的区域=膨胀结果-种子
    ret, markers = cv.connectedComponents(surface_fg)#联通区域

    # 分水岭变换
    markers = markers + 1
    markers[unknown == 255] = 0
    markers = cv.watershed(src, markers=markers)
    src[markers == -1] = [0, 0, 255]
    cv.imshow("result", src)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("coins.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
watershed_demo()
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

最后结果

电气专业的计算机萌新,写博文不容易。如果你觉得本文对你有用,请点个赞支持下,谢谢。

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览51048 人正在系统学习中
注:本文转载自blog.csdn.net的总裁余(余登武)的文章"https://blog.csdn.net/kobeyu652453/article/details/107406413"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top