一、简介

经典的前景提取技术主要使用纹理(颜色)信息,如魔术棒工具,或根据边缘(对比度)信息,如智能剪刀等完成。2004 年,微软研究院(剑桥)的 Rother 等人在论文 GrabCut: Interactive Foreground Exiraction Using lrerated Graph Cuts 中提出了交互式前景提取技术。他们提出的算
法,仅需要做很少的交互操作,就能够准确地提取出前景图像。

二、前景提取

在开始提取前景时,先用一个矩形框指定前景区域所在的大致位置范围,然后不断迭代地
分割,直到达到最好的效果。经过上述处理后,提取前景的效果可能并不理想,存在前景没有
提取出来,或者将背景提取为前景的情况,此时需要用户干预提取过程。用户在原始图像的副
本中(也可以是与原始图像大小相等的任意一幅图像),用白色标注要提取为前景的区域,
黑色标注要作为背景的区域。然后,将标注后的图像作为掩模,让算法继续迭代提取前景从而
得到最终结果。
       例如,对于下图所示的左图,先用矩形框将要提取的前景 Lena 框出来,再分别用白色和
黑色对前景图像、背景图像进行标注。完成标注后,使用交互式前景提取算法,就会得到图 17-14
右图所示的结果图像

PowerPoint 提供了 “删除背景,功能。用户可以根据需要,在图像上标注出需要保留的部分和需要删除的部分,然后让PowerPoint 帮助我们完成前景对象的提取。尝试在 PowerPoint中删除图像背景,会帮助我们更好地理解交 互,式前景提取时模板的使用方式。

三、GrabCut实现

下面我们来看 GrabCut 算法的具体实施过程:

  1. 将前景所在的大致位置使用矩形框标注出来。值得注意的是,此时矩形框框出的仅仅是前景的大致位置,其中既包含前景又包含背景,所以该区域实际上是未确定区域。但是,该区域以外的区域被认为是 “ 确定背景 ”。
  2. 根据矩形框外部的“确定背景” 数据来区分矩形框区域内的前景和背景。
  3. 用高斯混合模型 (Gaussians Mixture Model, GMM)对前景和背景建模。GMM 会根据用户的输入学习并创建新的像素分布。对未分类的像素(可能是背景也可能是前景),根据其与己知分类像素(前景和背景,的关系进行分类。
  4. 根据像素分布情况生成一幅图,图中的节点就是各个像素点。除了像素点之外,还有两个节点:前景节点和背景节点。所有的前景像素都和前景节点相连,所有的背景像素都和背景节点相连。每个像素连接到前景节点或背景节点的边的权重由像素是前景或背景的概率来决定。
  5. 图中的每个像素除了与前景节点或背景节点相连外,彼此之间还存在着连接。两个像素连接的边的权重值由它们的相似性决定,两个像素的颜色越接近,边的权重值越大。
  6. 完成节点连接后,需要解决的问题变成了一幅连通的图。在该图上根据各自边的权重关系进行切割,将不同的点划分为前景节点和背景节点。
  7. 不断重复上述过程,直至分类收敛为止。

在OpenCV 中,实现交互式前景提取的函数是 cv2.grabCut,其语法格式为:

mask, bgdModel, fgdModel = cv2. grabCut (img, mask, rect, bgdModel, fgaModel,
iterCount [, mode] ) 

式中:

img为输入图像,要求是8位3通道的。

mask为掩膜图像,要求是8位单通道的。该参数用于确定前景区域、背景区域和不确定区域,可以设置为4种形式。

  • cv2.GC_BGD: 表示确定背景,也可以用数值0表示
  • cv2.GC_FGD: 表示确定前景,也可以用数值1表示
  • cv2.GC_PR_BGD: 表示可能的背景,也可以用数值2表示
  • cv2.GC_PR_FGD: 表示可能的前景,也可以用数值3表示

在最好使用模板提取前景时,会将参数值0和2合并为背景(均当作0处理),将参数值1和3合并为前景(均当作1处理)。在通常情况下,我们可以使用白色笔刷和黑色笔刷在掩膜图像上做标记,再通过转换将其中的白色像素设置为0,黑色像素设置为1。

rect 指包舍前景对象的区域,该区域外的部分被认为是“确定背景”。因此,在选取时务必确保让前最包合在rect 指定的范围内;否则,rect 外的前景部分是不会被提取出来的。只有当参数mode 的值被设置为矩形模式 cv2.GC_INIT_WITH_RECT时,参数rect才有意义。其格式为 (x,y,w.h),分别表示区域左上角像素的x轴和y轴坐标以及区域的宽度和高度。如果前景位于右下方,又不想判断原始图像的大小,对于 w 和h可以直接用一个很大的值。使用掩模模式时,将该值设置为 none 即可。

  • bgdModel 为算法内部使用的数组,只需要创建大小为(1,65) 的 numpy.float64 数组。
  • fgdModel 为算法内部使用的数组,只需要创建大小为(1,65) 的 numpy.float64 数组。
  • iterCount 表示迭代的次数。
  • mode 表示迭代模式。其可能的值与含义如下表所示:
参数mode的值 含义
cv2.GC_INIT_WITH_RECT 使用矩形模块
cv2.GC_INIT_WITH_MASK 使用自定义模块。需要注意cv2.GC_INIT_WITH_RECT和cv2.GC_INIT_WITH_MASK能组合使用。所以ROI区域外(不在模板或矩形指定范围内)的像素自动被处理为背景。
cv2.GC_EVAL 修复模式
cv2.GC_EVAL_FREEZE_MODEL 使用固定模式

四、GrabCut示例

使用GrabCut算法提取图像的前景

import cv2
import numpy as np
import matplotlib.pyplot as plto = cv2.imread('lena.jpg')
orgb = cv2.cvtColor(o, cv2.COLOR_BGR2RGB)
mask = np.zeros(o.shape[:2], np.uint8)
bgdmodel = np.zeros((1, 65), np.float64)
fgdmodel = np.zeros((1, 65), np.float64)
rect = (50,50,400,500)
cv2.grabCut(o, mask, rect, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
ogc = o*mask2[:, :, np.newaxis]
ogc = cv2.cvtColor(ogc, cv2.COLOR_BGR2RGB)
plt.subplot(121)
plt.imshow(orgb)
plt.axis('off')
plt.subplot(122)
plt.imshow(ogc)
plt.axis('off')
plt.show()cv2.waitKey()
cv2.destroyAllWindows()

 结果:

我们可以看到,在不使用掩膜(掩膜值都设置为默认值0时),函数cv2.grabCut()的处理效果并不太好:提取左图的前景的时候,人物的帽子没有提取完整。对于有些图像,也有可能会将背景错误地提取出来。

为了得到完整地前景对象,需要做一些改进。这里对原始图像进行标注,将需要保留的部分设置为白色,将需要删除的部分设置为黑色。以标记好的图像作为模板,使用函数cv2.grabCut()完成前景提取。

这个过程主要包含以下步骤:

  1. 利用cv2.grabCut()在cv2.GC_INIT_WITH_RECT模型下对图像进行初步的前景提取,得到初步提取的结果图像og。
  2. 使用windows系统自带的笔刷工具,打开要提取前景的图像,比如lena
  3. 使用白色笔刷在希望提取的前景区域做标记
  4. 使用黑色笔刷在希望删除的背景区域做标记
  5. 将当前设置好的lena图像另存为模板图像m0
  6. 将模板图像m0中白色值和黑色值映射到模板m中。将模板图像m0中的白色值(像素值为255)映射为模板图像m中的确定前景(像素值为1),将模板图像m0中的黑色值(像素值为0)映射为模板图像m中的确定背景(像素值为0)。
  7. 以模板图像m作为函数cv2.grabCut()的模板参数(mask),对图像og完成前景提取。

需要注意的是,在上述步骤中,使用画笔标记的模板图像m0不能直接作为模板(即参数mask)使用。函数cv2.grabCut()要求,参数mask的值必须是cv2.GC_BGD(确定背景)、cv2.GC_FGD(确定前景)、cv2.GC_PR_BGD(可能的背景)、cv2.GC_PR_FGD(可能的前景),或者是0、1、2、3之中的值。此时的模板图像m0中。存在着【0,255】内的值,所以它的值不满足函数cv2.grabCut()的要求,无法作为参数mask的使用。必须先将模板图像m0中白色值和黑色值映射到模板m上,再将模板图像m作为函数cv2.grabCut()的模板参考。

import cv2
import numpy as np
import matplotlib.pyplot as plto = cv2.imread('lena.jpg')
orgb = cv2.cvtColor(o, cv2.COLOR_BGR2RGB)
mask = np.zeros(o.shape[:2], np.uint8)
bgd = np.zeros((1, 65), np.float64)
fgd = np.zeros((1, 65), np.float64)
rect = (50, 50, 400, 500)
cv2.grabCut(o, mask, rect, bgd, fgd, 5, cv2.GC_INIT_WITH_RECT)
mask2 = cv2.imread('lenacolor.jpg', 0)
mask2show = cv2.imread("lenacolor.jpg", -1)
m2rgb = cv2.cvtColor(mask2show, cv2.COLOR_BGR2RGB)
mask[mask2 == 0] = 0
mask[mask2 == 255] = 1
mask, bgd, fgd = cv2.grabCut(o, mask, None, bgd, fgd, 5, cv2.GC_INIT_WITH_MASK)
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
ogc = o*mask[:, :, np.newaxis]
ogc = cv2.cvtColor(ogc, cv2.COLOR_BGR2RGB)
plt.subplot(121)
plt.imshow(m2rgb)
plt.axis('off')
plt.subplot(122)
plt.imshow(ogc)
plt.axis('off')
plt.show()cv2.waitKey()
cv2.destroyAllWindows()

 

图像分割与提取:交互式前景提取(附OpenCV代码实现)相关推荐

  1. OpenCV中的图像处理 —— 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

    OpenCV中的图像处理 -- 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

  2. OpenCV使用 GrabCut 算法进行交互式前景提取

    OpenCV使用 GrabCut 算法进行交互式前景提取 1. 效果图 2. 源码 参考 这篇博客将介绍如何使用Python,OpenCV中的GrabCut 算法来提取图像中的前景,并为此创建一个交互 ...

  3. OpenCV系列之交互式前景提取使用GrabCut算法 | 三十五

    目标 在本章中, 我们将看到GrabCut算法来提取图像中的前景 我们将为此创建一个交互式应用程序. 理论 GrabCut算法由英国微软研究院的Carsten Rother,Vladimir Kolm ...

  4. opencv29:使用Grabcut算法的交互式前景提取

    目标 在这一章当中 看到 GrabCut算法来提取图像中的前景 为此创建一个交互式应用程序 理论 GrabCut 算法由英国剑桥微软研究院的 Carsten Rother.Vladimir Kolmo ...

  5. Python OpenCV 交互式前景提取 自动抠图

    这是需要抠图的原图像,文件名为 "messi5.jpg" 使用矩形方式处理: # -*- coding: utf-8 -*-import numpy as np import cv ...

  6. 【OpenCV-Python】教程:3-16 利用Grabcut交互式前景提取

    OpenCV Python Grabcut分割 [目标] Grabcut 算法 创建一个交互程序 [理论] 从用户角度是如何工作的呢?用户在需要的目标上初始绘制一个矩形,前景目标必须完全在矩形内部,算 ...

  7. OpenCV视频分析背景提取与前景提取

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 基本思想 OpenCV中支持的两种背景提取算法都是基于模型密度评估 ...

  8. OpenCV—python 视频分析背景提取与前景提取

    文章目录 一.算法 二.代码 MOG2(Mixture of Gaussian) 与 KNN对比 Kmeans 行人检测代码 OpenCV中支持的两种背景提取算法都是 基于模型密度评估,然后在 像素级 ...

  9. 迭代图像切割技术的交互式前景提取

    ----- -----<"GrabCut" - Interactive Foreground Extraction using Iterated Graph Cuts> ...

最新文章

  1. iOS infoplist 权限设置
  2. .NET(C#):警惕PLINQ结果的无序性
  3. SD-WAN技术三大优势将成为SD-WAN方案成功的关键—Vecloud
  4. getResources()方法
  5. Spark RDD并行度与分区设置
  6. 检测范围_论文检测系统的检测范围有哪些
  7. c语言sleep函数_做游戏,学C语言,小球碰撞游戏,菜鸡者从黑窗口到图形化编程...
  8. 构建用于Openstack Heat的Linux映像
  9. python-socket模块介绍
  10. MySQL8.0数据库配置注意事项
  11. MS UC 2013-2-Deploy Microsoft Exchange Server 2013-1-Prerequisites
  12. 小米android安装包下载安装,小米应用商店安装包下载
  13. js保留两位小数并四舍五入的方法
  14. Android 9.0系统源码_SystemUI(六)滑动锁屏的创建
  15. 哪款无线蓝牙耳机性价比高?性价比高的无线蓝牙耳机推荐
  16. 移动端弹出层滚动时禁止body滚动
  17. c语言编写英语词典软件,C语言课程设计一种简单的英文词典排版系统的实现.doc...
  18. 活动目录功能级别降级
  19. 成功的演讲需要些什么
  20. 头歌MySQL数据库实训答案 有目录

热门文章

  1. Android平台简介
  2. 贪心算法——区间选点问题
  3. postgresql-COALESCE函数、NULLIF函数、NVL函数使用
  4. 利用微信小程序实现web监控界面
  5. 2020煤矿安全监测监控模拟考试题库及煤矿安全监测监控作业考试题库
  6. TCP/IP协议详解篇一(基础)
  7. php对接java接口(丁香医生)aes加解密-PKCS5Padding,rsa加解密
  8. 指责TD的人几个是有资格的?--艾瑞网专家项立刚的博客专栏 - 艾瑞网
  9. H5/APP客服端源码/uniapp在线客服系统源码开源了,全源码代码解读及发行安装教程...
  10. 浅谈Wi-Fi渗透--原理篇