首页 > 其他分享 >opencv实战项目二十九:GrabCut分割人像

opencv实战项目二十九:GrabCut分割人像

时间:2024-09-30 09:23:25浏览次数:9  
标签:img opencv GrabCut 前景 cv2 像素 二十九 算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

在数字图像处理领域,人像分割是一项极具挑战性的任务,它旨在从复杂背景中准确提取出人物图像。随着技术的不断发展,人像分割技术在许多领域都展现出了广泛的应用前景,如摄影后期处理、视频监控、虚拟现实等。在这其中,GrabCut 算法作为一种高效、精确的图像分割方法,备受关注。本文将带你深入了解 GrabCut 算法,探讨如何利用它来实现人像的精确分割,让你在处理图像时能够轻松应对复杂背景,为创作和科研带来更多可能性。

一、GrabCut介绍:

GrabCut 是一种迭代的图割(Graph Cut)算法,由微软研究院的 Carsten Rother、Vladimir Kolmogorov 和 Andrew Blake 在2004年提出。它用于从静态图像中分离出前景对象和背景,通常只需要用户提供一个矩形框来大致标记前景对象,就能自动完成精确的分割。

以下是 GrabCut 算法的基本步骤和原理:

  1. 初始化
    用户输入:用户在图像中绘制一个矩形框,框内大致包含前景对象。
    背景/前景标记:矩形框内的像素被标记为可能的前景(T),矩形框外的像素被标记为可能的背景(B)。
  2. 高斯混合模型(GMM)
    模型训练:算法使用高斯混合模型来建模前景和背景的颜色分布。每个组件(前景或背景)都由一个高斯分布表示,这些分布的参数通过迭代优化来估计。
    像素分配:每个像素根据其颜色被分配给前景或背景的高斯分布之一,分配的过程会影响分布参数的更新。
  3. 图构建
    节点:图像中的每个像素对应图中的一个节点。
    边:节点之间通过边连接,边的权重表示像素之间的相似度。通常,像素之间的相似度是基于颜色差异来计算的。
    源点和汇点:图中有两个特殊的节点,源点(source)和汇点(sink)。源点连接所有标记为前景的像素,汇点连接所有标记为背景的像素。
  4. 能量最小化
    能量函数:算法定义了一个能量函数,它由数据项和光滑项组成。数据项表示像素属于前景或背景的概率,光滑项则惩罚相邻像素属于不同区域的决策。
    图割:通过最小化能量函数,GrabCut 算法在图中进行切割,将节点分为两部分,一部分连接到源点(前景),另一部分连接到汇点(背景)。
  5. 迭代优化
    迭代更新:在初次图割之后,算法可能会根据切割结果更新GMM模型中的参数,然后重新进行图割。
    用户反馈:用户可以提供额外的反馈,如标记某些像素为前景或背景,以改进分割结果。
  6. 输出结果
    前景提取:最终,GrabCut 算法输出一个前景掩码(mask),其中包含被分割出来的前景对象。

GrabCut 算法的优势在于它能够处理较为复杂的背景,并且用户交互简单,通常只需要提供一个矩形框即可。然而,它也有局限性,比如对于透明物体或颜色与背景相似的前景对象,GrabCut 可能无法达到理想的分割效果。此外,GrabCut 算法假设图像中的前景对象颜色分布是连贯的,这在某些情况下可能不成立。尽管如此,GrabCut 仍然是一个非常实用的图像分割工具,广泛应用于各种图像处理任务中。

二、opencv实现:

在opecv中有grabcut算法的api:retval, mask = cv2.grabCut(img, mask, rect, bgd_model, fgd_model, iter_count, mode),下面是 cv2.grabCut 函数的参数介绍:
输入:

img: 待分割的输入图像,通常是 8 位 3 通道(RGB)图像。
mask: 与输入图像大小相同的掩码图像,用于标记每个像素的状态。掩码图像可以是以下几种值之一:
cv2.GC_BGD: 背景像素(可能背景)
cv2.GC_FGD: 前景像素(可能前景)
cv2.GC_PR_BGD: 可能背景像素
cv2.GC_PR_FGD: 可能前景像素
cv2.GC_INIT_WITH_RECT: 初始化模式,使用矩形框
rect: 一个矩形元组 (x, y, w, h),其中 (x, y) 是矩形的左上角坐标,(w, h) 是矩形的宽度和高度。这个矩形框用于初始化前景对象的大致位置。
bgd_model: 用于背景模型的高斯混合模型(GMM)的数组,通常初始化为 np.zeros((1, 65), np.float64)。
fgd_model: 用于前景模型的高斯混合模型(GMM)的数组,通常初始化为 np.zeros((1, 65), np.float64)。
iter_count: 迭代优化的次数。GrabCut 算法会在每次迭代中更新 GMM 参数和像素标签,更高的迭代次数可能会得到更好的结果,但也会增加计算时间。
mode: GrabCut 算法的运行模式。以下是两种可能的模式:
cv2.GC_INIT_WITH_RECT: 使用矩形框初始化 GrabCut,这是最常用的模式。
cv2.GC_INIT_WITH_MASK: 使用掩码初始化 GrabCut,在这种情况下,掩码应该已经包含了用户提供的初步前景和背景信息。

函数返回两个值:

retval: 表示算法是否成功执行。
mask: 更新后的掩码图像,其中包含了最终的分割结果。掩码中的值将被更新为以下几种:
0: 背景像素
1: 前景像素
2: 可能背景像素
3: 可能前景像素

使用代码:

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 读取图像
img = cv2.imread(r'D:\AI_tool\GFPGAN-master\R-C (3).jfif')
# 将图像转换为RGB格式,以便在matplotlib中显示
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 定义矩形区域,GrabCut需要这个来初始化
# rect = (x, y, width, height)
rect = (50, 50, img.shape[1] - 100, img.shape[0] - 100)

# 创建一个掩码,用于GrabCut算法
# 初始化掩码为全零矩阵,前景和背景由GrabCut算法更新
mask = np.zeros(img.shape[:2], np.uint8)

# 创建前景和背景模型,算法内部使用
bgd_model = np.zeros((1, 65), np.float64)
fgd_model = np.zeros((1, 65), np.float64)

# 使用GrabCut算法进行图像分割
cv2.grabCut(img, mask, rect, bgd_model, fgd_model, 5, cv2.GC_INIT_WITH_RECT)

# 更新掩码,将0和2转换为0(背景),将1和3转换为1(前景)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')

# 将掩码应用到图像上,得到分割后的前景
img_rgb_fg = img_rgb * mask2[:, :, np.newaxis]

# 显示原始图像和分割后的前景
plt.figure(figsize=(10, 5))
plt.subplot(121)
plt.imshow(img_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(122)
plt.imshow(img_rgb_fg)
plt.title('Foreground')
plt.axis('off')

plt.show()

三、效果:

在这里插入图片描述

标签:img,opencv,GrabCut,前景,cv2,像素,二十九,算法
From: https://blog.csdn.net/HanWenKing/article/details/142619865

相关文章

  • 《OpenCV 计算机视觉》—— Harris角点检测、SIFT特征检测
    文章目录一、Harris角点检测1.基本思想2.检测步骤3.OpenCV实现二、SIFT特征检测1.SIFT特征检测的基本原理2.SIFT特征检测的特点3.OpenCV实现一、Harris角点检测OpenCV中的Harris角点检测是一种基于图像灰度值变化的角点提取算法,它通过计算每个像素点的响应函......
  • 基于OpenCV的实时年龄与性别识别(支持CPU和GPU)
    关于深度实战社区我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万+粉丝,拥有2篇国家级人工智能发明专利。社区特色:深度实战算法创新获取全部完整项目......
  • 《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析
    目录一、透视变换1、什么是透视变换2、操作步骤    1)选择透视变换的源图像和目标图像    2)确定透视变换所需的关键点    3)计算透视变换的变换矩阵    4)对源图像进行透视变换    5)对变换后的图像进行插值处理二、轮廓检测1、......
  • 03_OpenCV像素操作
    importcv2img=cv2.imread('libaray.JPG',1)(b,g,r)=img[100,100]print(b,g,r)#bgr#10100---110100i=j=0forjinrange(1,500):img[i,j]=(255,255,255)foriinrange(1,500):img[i,j]=(255,255,255)#cv2.imshow('......
  • QT 获取视频帧Opencv获取清晰度
    先展示结果:1.获取摄像头的分辨率mResSize.clear();mResSize=camera_->supportedViewfinderResolutions();ui->comboBox_resulation->clear();inti=0;foreach(QSizemsize,mResSize){qDebug()<<msize;ui->comboBox_re......
  • OpenCV(cv::multiply())
    目录1.函数定义2.功能说明3.示例3.1基础逐元素相乘3.2带缩放因子的逐元素相乘3.3处理不同数据类型4.注意事项5.高级用法5.1使用掩码进行选择性相乘总结cv::multiply()是OpenCV库中用于对两个数组(通常是图像)的对应元素进行逐元素相乘的函数。1.函数定义namespa......
  • OpenCV视频I/O(3)视频采集类VideoCapture之获取当前使用的视频捕获 API 后端的名称函数
    操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:VisualStudioCode编程语言:C++11算法描述getBackendName函数是OpenCV中VideoCapture类的一个方法,用于获取当前使用的视频捕获API后端的名称。这可以帮助开发者了解当前VideoCapture实例正在使用哪个后端来处理视......
  • OpenCV视频I/O(2)视频采集类VideoCapture之检索视频流的各种属性函数get()的使用
    操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:VisualStudioCode编程语言:C++11算法描述返回指定的VideoCapture属性。VideoCapture的get()函数用于检索视频流的各种属性。这个函数允许你查询视频源的状态和配置,例如分辨率、帧率等。函数原型virtualdoublec......
  • OpenCV(cv::mean())
    目录1.函数定义2.示例2.1计算灰度图像的平均值2.2计算彩色图像的每个通道的平均值2.3带掩码的平均值计算总结cv::mean()是OpenCV中用于计算图像的平均值的函数。它可以用于单通道图像、多通道图像(如彩色图像)、带掩码的图像等。1.函数定义Scalarcv::mean(InputArr......
  • 综合实验1 利用OpenCV统计物体数量
    一、实验简介传统的计数方法常依赖于人眼目视计数,不仅计数效率低,且容易计数错误。通常现实中的对象不会完美地分开,需要通过进一步的图像处理将对象分开并计数。本实验巩固对OpenCV的基础操作的使用,适当的增加OpenCV在图像处理方向的进阶操作,例如利用canny算子等算法进行图像分......