从零开始学cv-15:图像分割

news2024/10/5 4:21:43

文章目录

  • 前言
  • 一、全局阈值分割:
  • 二、自适应阈值分割:
  • 三、分水岭算法:


前言

在当代计算机视觉领域,图像分割技术扮演着至关重要的角色,它为图像理解、目标识别和场景解析等高级视觉任务提供了基础。OpenCV,作为一款广泛应用于工业和学术界的开源计算机视觉库,提供了丰富的算法和工具,使得图像分割技术的实现变得更为便捷和高效,本文旨在深入探讨OpenCV在图像分割方面的应用,从理论到实践,全面剖析各种分割算法的实现原理和操作步骤。

一、全局阈值分割:

全局阈值分割是一种基本的图像分割方法,它将图像中的像素分为两类:前景和背景。这种分割方法基于一个全局阈值,该阈值适用于图像中的所有像素。
步骤:

  1. 选择阈值:选择一个灰度值作为阈值。这个值可以是固定的,也可以通过某种算法自动确定,例如Otsu方法。
  2. 应用阈值:对于图像中的每个像素,如果像素的灰度值大于或等于阈值,则将其分类为前景;如果小于阈值,则分类为背景。

在opencv中提供了其api:ret, thresh = cv2.threshold(img, threshold_value, 255, cv2.THRESH_BINARY):
参数说明:
src: 输入图像,通常是 8 位单通道图像(灰度图像)。
thresh: 阈值,用于决定像素是否被设置为 maxval 或 0。
maxval: 当像素值超过阈值时,要赋予的像素值。通常对于二值图像,这个值是 255。
type: 阈值类型,决定了如何处理阈值操作。以下是几种常见的阈值类型:

  1. cv2.THRESH_BINARY: 如果像素值大于阈值,则将其设置为 maxval;否则设置为 0。
  2. cv2.THRESH_BINARY_INV: 如果像素值大于阈值,则将其设置为 0;否则设置为 maxval。
  3. cv2.THRESH_TRUNC: 如果像素值大于阈值,则将其设置为阈值;否则不改变。
  4. cv2.THRESH_TOZERO: 如果像素值大于阈值,则不改变;否则设置为 0。
  5. cv2.THRESH_TOZERO_INV: 如果像素值大于阈值,则设置为 0;否则不改变。
  6. cv2.THRESH_OTSU: 使用 Otsu 方法自动计算最佳阈值,并将其设置为阈值。
  7. cv2.THRESH_TRIANGLE: 使用 Triangle 方法自动计算最佳阈值,并将其设置为阈值。

返回值:
retval: 函数返回的阈值,这在应用 Otsu 或 Triangle 自动阈值方法时非常有用。
dst: 阈值处理后的输出图像。
注:
其中Otsu和Triangle算法不需要设置阈值,它们会根据图像的特征自动选择一个合适的阈值,Otsu算法通过遍历所有可能的灰度阈值,计算每个阈值下的前景和背景的类间方差,并选择使得类间方差最大的阈值作为最佳分割阈值,从而实现图像的二值化。
Triangle分割算法是一种基于图像直方图形状的阈值确定方法,通过寻找直方图与背景和对象之间的“三角形”区域的重心来确定最佳阈值,适用于直方图不呈现明显双峰分布的图像,对噪声和不均匀分布具有较好的鲁棒性。

  • 如果图像的直方图具有明显的双峰特性,Otsu方法通常能提供更好的分割效果。如果直方图没有明显的双峰或者图像的对比度较低,Triangle方法可能更合适。
  • Otsu方法对噪声较为敏感,因为噪声可能会导致直方图的双峰特性不明显。Triangle方法在这种情况下可能更为鲁棒。

使用:

import cv2

# 读取灰度图像
img = cv2.imread(r'D:\AI_tool\GFPGAN-master\1.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img_show = cv2.resize(img,(0,0),fx=0.3,fy=0.3)
img_re = cv2.resize(img_gray,(0,0),fx=0.3,fy=0.3)
# 应用阈值处理
ret, thresh = cv2.threshold(img_re, 127, 255, cv2.THRESH_BINARY)
ret2, thresh2 = cv2.threshold(img_re, 0, 255, cv2.THRESH_OTSU)
ret3, thresh3 = cv2.threshold(img_re, 0, 255, cv2.THRESH_TRIANGLE)
# 显示结果
cv2.imshow('Image', img_show)
cv2.imshow('Thresholded Image', thresh)
cv2.imshow('OTSU Image', thresh2)
cv2.imshow('TRIANGLE Image', thresh3)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:
在这里插入图片描述

二、自适应阈值分割:

自适应阈值分割是一种图像处理技术,它根据图像的不同区域特性自动调整阈值,以实现更准确的图像分割。这种方法不同于全局阈值分割,后者在整个图像上使用一个固定的阈值。自适应阈值分割的目的是解决图像中光照不均或对比度变化的问题,其基本思想是局部区域内的像素值应该足够相似,以便可以被正确地分为前景或背景。
自适应阈值分割的步骤通常包括:

  1. 选择一个合适大小的窗口(如奇数大小的正方形或圆形窗口)。
  2. 在每个窗口内计算阈值,通常是基于窗口内像素的均值或中值,并减去一个常数(如C),即阈值 = 局部均值 - C。
  3. 将每个像素与其对应窗口的阈值进行比较,以确定该像素是前景还是背景。
  4. 移动窗口遍历整个图像,重复上述过程。

在opencv中存在其对应的api:cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
参数说明:
src: 输入图像,通常是一个灰度图像。
maxValue: 阈值最大值,通常设置为255。
adaptiveMethod: 自适应方法,有以下两种选择:
cv2.ADAPTIVE_THRESH_MEAN_C: 阈值是邻域区域的平均值减去常数C。
cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 阈值是邻域区域的高斯加权和减去常数C。
thresholdType: 阈值类型,有以下两种选择:
cv2.THRESH_BINARY: 如果像素值大于阈值,则设为最大值,否则设为0。
cv2.THRESH_BINARY_INV: 如果像素值大于阈值,则设为0,否则设为最大值。
blockSize: 邻域大小,必须是奇数,如3、5、7等。
C: 从平均值或加权平均值中减去的常数,通常是一个正数。
使用代码:

import cv2

# 读取灰度图像
img = cv2.imread(r'D:\AI_tool\GFPGAN-master\1.jpg')
img = cv2.resize(img,(0,0),fx=0.3,fy=0.3)


# 2. 灰度转换
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 3. 高斯模糊
blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)

# 4. 自适应阈值分割
# 使用ADAPTIVE_THRESH_MEAN_C,blockSize为11,常数C为2
adaptive_thresh = cv2.adaptiveThreshold(blurred_image, 255,
                                        cv2.ADAPTIVE_THRESH_MEAN_C,
                                        cv2.THRESH_BINARY, 31,3)

# 5. 结果展示
cv2.imshow('Original Image', img)
cv2.imshow('Adaptive Thresholding', adaptive_thresh)

# 等待按键后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()


效果:
在这里插入图片描述

三、分水岭算法:

分水岭算法是一种基于拓扑理论的图像分割方法,它将图像看作一个地形图,其中亮度较高的区域被视为山峰,亮度较低的区域被视为山谷。算法的基本思想是模拟水在山谷中流动并最终汇集到一起的过程,直到水从山顶溢出,从而在各个山峰之间形成分水岭。
其实现流程为:

  1. 初始化:将图像看作一个三维地形图,其中灰度值表示高度。
  2. 淹没:从最低点开始,模拟水逐渐淹没整个地形。随着水位的上升,不同的盆地被水填满。
  3. 构建分水岭:当水位继续上升并接触到不同盆地的边缘时,在这些边缘处构建堤坝(分水岭)。堤坝防止不同盆地中的水相互混合。
  4. 标记:当所有的盆地都被堤坝分隔开后,每个盆地都会被赋予一个独特的标记。
  5. 合并:在实际应用中,会合并非常接近的盆地,以减少过分割的问题。

分水岭算法的关键步骤包括:

  1. 预处理:通常需要对图像进行预处理,如滤波、二值化、形态学操作等,以减少噪声和突出图像特征。
  2. 标记:在图像中标记出已知的前景和背景区域。这些标记将作为分水岭算法的种子点。
  3. 实施分水岭:使用标记过的图像作为输入,实施分水岭算法,从而得到分割后的图像。

分水岭算法的优点是能够提供连续、闭合、单调的分割边界,并且能够处理具有复杂形状的物体。然而,它也有缺点,比如对噪声敏感,容易产生过分割现象,即图像被分割成过多的区域。
在opencv中有实现分水岭算法的api:retval, markers = cv2.watershed(image, markers),
参数说明:

输入:
image:
类型:8位3通道图像。
说明:这是输入图像,通常是经过预处理后的图像,比如已经进行了灰度转换、滤波、边缘检测等操作。
markers:
类型:32位单通道图像,与image具有相同的大小。
说明:这是标记图像,其中每个区域的标记是通过不同的正整数来表示的。通常,前景对象用正值标记,背景用0标记,未知区域用-1标记。标记图像可以通过用户交互或者使用其他图像分割技术(如阈值分割、边缘检测、区域生长等)来生成。

返回值:
retval:
类型:与markers相同的图像。
说明:这是分割后的图像,其中边界区域被标记为-1。
markers:
类型:与输入的markers相同,但是经过函数处理后,标记图像中的每个区域都会被赋予一个唯一的标签。

使用 cv2.watershed 函数的步骤通常如下:

  1. 读取或创建原始图像。
  2. 对图像进行预处理,比如转换为灰度图像、应用滤波器、边缘检测等。
  3. 创建标记图像,初始化前景、背景和未知区域。
  4. 应用 cv2.watershed 函数。
  5. 根据返回的 markers 图像进行后处理,例如用颜色标记不同区域,或者提取分割后的区域。

代码案例:

import cv2
import numpy as np

# 读取图像
image = cv2.imread(r'D:\AI_tool\GFPGAN-master\1.jpg')
if image is None:
    print("Error: Image cannot be loaded. Please check the path.")
    exit()

image = cv2.resize(image,(0,0),fx=0.3,fy=0.3)

# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 应用高斯模糊,减少图像噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)

# 使用二值化方法初始化前景
_, thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)

# 定义一个kernel,用于形态学操作
kernel = np.ones((3,3), np.uint8)

# 形态学开操作,去除小的白色噪点
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=2)

# 寻找前景区域,通过距离变换和阈值处理
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)

# 找到未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

# 创建标记
ret, markers = cv2.connectedComponents(sure_fg)

# 为背景添加一个标记,标记为1而不是0,因为0是未知区域
markers = markers + 1

# 未知区域标记为0
markers[unknown == 255] = 0

# 应用分水岭算法
markers = cv2.watershed(image, markers)

# 将边界标记为红色
image[markers == -1] = [0, 0, 255]

# 显示结果
cv2.imshow('Watershed Segmented Image', sure_bg)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis:hash类型

Redis:hash类型 hash命令设置与读取HSETHGETHMGET 哈希操作HEXISTSHDELHKEYSHVALSHGETALLHLENHSETNXHINCRBYHINCRBYFLOAT 内部编码ziplisthashtable 目前主流的编程语言中,几乎都提供了哈希表相关的容器,Redis自然也会支持对应的内容&#xf…

李宏毅深度学习-循环神经网络RNN

Recurrent Neural Network 这个问题可以使用一个前馈神经网络(feedforward neural network)来解,如图5.2 所示, 输入是一个单词,把“上海”变成一个向量,“丢”到这个神经网络里面。输入是一个单词&#x…

平衡二叉搜索树---java---黑马

平衡二叉搜索树 AVL树的实现 二叉搜索树在插入和删除时,节点可能发生失衡;如果在插入和删除时通过旋转,始终让二叉搜索树保持平衡,称之为平衡二叉搜索树;AVL树是自平衡二叉搜索树的实现之一 LL - 失衡节点(图中5红…

项目-坦克大战学习笔记-地图完善

之前我们详细讲解了怎么在地图上绘制墙&#xff0c;这次我们来完善整个地图&#xff0c; 地图的静态物体构成分为可破坏的墙体&#xff0c;不可破坏的铁块&#xff0c;以及最终boos 那我们为了方便存储将三个对象分开放为3个列表 private static List<gudin> walllist…

vscode有问题

开始给我报错&#xff0c;说命名不规范 然后我就改&#xff0c;改了好几遍之后还是报错。问了ai&#xff0c;也用它的方法改了&#xff0c;还是报错。。。 然后关掉vscode&#xff0c;重启&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c;运行成功

【算法系列-链表】删除链表的倒数第N个结点

【算法系列-链表】删除链表的倒数第N个结点 文章目录 【算法系列-链表】删除链表的倒数第N个结点1. 算法分析&#x1f6f8;2. 模拟解决问题2.1 思路分析&#x1f3af;2.2 代码示例&#x1f330; 3. 双指针(快慢指针)解决问题3.1 思路分析&#x1f3af;3.2 代码示例&#x1f330…

Web-Machine-N7解题过程

1.主机探测 arp-scan -lnmap -sn 192.168.1.0/24sudo netdiscover -r 192.168.1.0/24masscan -p0-65535 192.168.1.0/24 2.端口扫描 nmap -A -sC -sT -sV 192.168.1.188 --min-rate 10000 &#xff08;简略扫描&#xff09;nmap -sS 192.168.1.188 -A&#xff1a; 启用操作系…

vue的图片显示

通过参数 调用方法 进行显示图片 方法一: 方法二:

使用TM1618控制LED了解P-MOS和N-MOS的开漏输出的不同

数据手册上的截取内容 推荐的共阴/阳极电路 可以发现GRID总接LED的负极&#xff0c;SEG引脚接的是LED 正极 分析输出的MOS管类型可以很好的知道原因 图片来源 通过都是开漏输出可以看出&#xff0c;引脚引出的内部电路是不同的。P-mos引出的是漏极&#xff0c;导通时&#…

平面电磁波的能量传输速度——就记平均坡印廷矢量/平均能量密度(物理意义,坡印廷是单位时间该点流过的能量,能量密度表示该店有多少能量。如果能量密度不变,经过流动速度是2/s,则1s流过的能量就是2*密度

能量传输速度 平均坡印廷矢量的模&#xff08;功率流密度&#xff09;/ 电磁波平均能量密度&#xff08;电场和磁场的都算进去&#xff09; 能量传输速度等于相速度 但是文心给出的能量流动速度的定义是

2. 术语解释(类、成员变量、行为、属性、this)以及注销账号和空指针异常

文章目录 1. 类2. 成员变量3. 行为4. 属性5. zhangDog.name 以及 zhangDog.sleep()解析6. this① 提出问题② 解决方案③ 进一步完善&#xff1a;引入this 7. 注销账号8. 空指针异常9. 内容出处 1. 类 我们的目的是不是要给狗写一个程序&#xff0c;而且要让所有狗都能用&#…

20241004给荣品RD-RK3588-AHD开发板刷Rockchip原厂的Android12【HDMI0显示】

20241004给荣品RD-RK3588-AHD开发板刷Rockchip原厂的Android12【HDMI0显示】 2024/10/4 19:40 1、配置RK3588S的默认DTS为&#xff1a;rk3588s-evb4-lp4x-v10.dts D:\Android\rk3588s4_3588a12\device\rockchip\rk3588\rk3588s_s\BoardConfig.mk Z:\rk3588s4_3588a12\device\ro…

【论文笔记】Efficient LoFTR: Semi-Dense Local Feature Matching with Sparse-Like Speed

【引用格式】&#xff1a;Wang Y, He X, Peng S, et al. Efficient LoFTR: Semi-dense local feature matching with sparse-like speed[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2024: 21666-21675. 【网址】&#xff1a;ht…

PostgreSQL Docker Error – 5432: 地址已被占用

PostgreSQL Docker Error – 5432: 地址已被占用 今天在学习【Spring Boot React】价值79.9美元&#xff0c;全栈开发&#xff0c;搭建个人网站、做毕业设计、试试这套课程第17~21节视频的时候&#xff0c;发现运行docker run --name demo-postgres -e POSTGRES_PASSWORDpass…

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据量&#xff1a;3k 想要进一步了解&#xff0c;请联系。 DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种…

高效参数微调

一、增加额外参数的方法 这些方法通过向模型中添加额外的可训练参数&#xff0c;而不修改原有的预训练模型参数。 1. Prefix Tuning&#xff08;前缀微调&#xff09; 原理&#xff1a;在每一层的输入添加一组可训练的“前缀”向量&#xff0c;这些前缀向量会影响模型的输出…

使用PL/SQL Deverloper过程遇见的问题

目录 背景: ORA-01031权限问题&#xff1a; PL/SQL Deverloper显示Oravle中存在的所有表&#xff1a; PL/SQL Deverloper优点: 背景: PL/SQL Developer是由Allround Automations公司开发的一款集成开发环境(IDE),它专门面向Oracle数据库存储的程序单元的开发。随着越来越多…

Python+Matplotlib可视化初等函数示例

import numpy as np import matplotlib.pyplot as pltplt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] Falsefig, axs plt.subplots(2, 3, figsize(15, 10))# 1. 幂函数 x np.linspace(-2, 2, 200) axs[0, 0].plot(x, x**2, labely x^2) axs[0,…

每日OJ题_牛客_OR63删除公共字符_哈希_C++_Java

目录 牛客_OR63删除公共字符_哈希 题目解析 C代码1 C代码2 Java代码 牛客_OR63删除公共字符_哈希 删除公共字符_牛客题霸_牛客网 (nowcoder.com) 题目解析 用哈希表记录一下字符串的字符信息即可。 C代码1 #include <iostream> #include <string> #includ…

C语言 动态数据结构的C语言实现内存映像

C程序的内存映像 C程序中变量的内存分配方式  C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量 C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量  在栈上分配  存放函数参数值&#xff0c;局部变量值等  …