交互式前景提取---OpenCV-Python开发指南(37)

简介: 交互式前景提取---OpenCV-Python开发指南(37)

什么是交互式前景提取


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


在开始提取前景时,先用一个矩形框指定前景区域所在的大致位置范围,然后不断迭代地分割,直到达到最好的效果。经过上述处理后,提取前景的效果可能并不理想,存在前景没有提取出来,或者将背景提取为前景的情况,此时需要用户干预提取过程。用户在原始图像的副本中(也可以是原始图像大小相等的任意一副图像),用白色标注要提取为前景的区域,用黑色标注要作为背景的区域,然后,将标注后的图像作为掩模,让算法继续迭代提取前景从而得到最终的结果。


比如上图这种人物图像,先用矩形框将要提取的前景框出来,在分别用白色和黑色对前景图像,背景图像进行标注。标注完成之后,使用交互式前景提取算法,就可以提取人物的完整前景了。


下面,博主来详细介绍交互式前景提取算法GrabCut算法的原理:


1.将前景所在的大致区域位置使用矩形框标注出来。值得注意的是,此时的矩形框框出的仅仅是前景的大致位置,其中即包含前景又包含背景,所以该区域实际上是未确定区域。但是该区域以外的区域被认为是“确定背景”

2.根据矩形框外部的“确定背景”数据来区分矩形框区域内的前景和背景。

3.用高斯混合模型(GMM)对前景和背景建模。GMM会根据用户的输入学习并创建新的像素分布。对未分类的像素(可能是背景也可能是前景),根据其与已知分类像素(前景和背景)的关系进行分类。

4.根据像素的分布情况生成一副图,图中的节点就是各个像素点。除了像素点之外,还有两个节点:前景节点和背景节点。所有的前景像素都和前景节点相连,所有的背景像素都和背景节点相连。每个像素连接到前景节点或背景节点的边的权重由像素是前景或背景的概率来决定

5.图中的每个像素除了与前景节点或背景节点相连外,彼此之间还存在着连接。两个像素连接的边的权重值由它们的相似性决定,两个像素值的颜色越接近,边的权重值越大。

6.完成节点连接后,需要解决的问题变成了一副连通的图。在该图上根据各自边的权重关系进行切割,将不同的点划分为前景节点和背景节点。

7.不断重复上述过程,直到分类收敛为止。


grabCut函数


OpenCV中,它给我们提供了cv2.grabCut()函数来实现交互式前景提取,其完整定义如下:

def grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode=None): 

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:迭代模式,具体取值如下表:

取值

含义
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 使用固定模式


提取图像前景


既然我们了解了原理,也知道了OpenCV提供的方法。下面,我们来试着提取上述图像的前景,代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg")
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.axis('off')
mask = np.zeros(img.shape[:2], dtype=np.uint8)
bgdModel = np.zeros((1, 65), dtype=np.float64)
fgdModel = np.zeros((1, 65), dtype=np.float64)
mask[10:200, 95:220] = 3
cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
ogc = img * mask2[:, :, np.newaxis]
plt.subplot(122)
plt.imshow(ogc, cmap="gray")
plt.axis('off')
plt.show()


运行之后,我们可以完全分离出人脸与背景,效果如下:

至于mask取值为什么会是这样,我们先来看看如下代码:

import cv2
img = cv2.imread("4.jpg")
rect=img[10:200,95:220]
cv2.imshow("4",rect)
cv2.waitKey()
cv2.destroyAllWindows()


运行之后,效果如下:


可以看到,10:200, 95:220是坐标(10,95)宽高200,220的矩形框,也就是可能前景的矩形框。通过可能前景加上CrabCut算法,我们获取确定前景(这里是人物头部)。


使用模板提取图像前景


下面,我们直接使用cv2.GC_INIT_WITH_MASK来提取。代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg")
mask = np.zeros(img.shape[:2], dtype=np.uint8)
bgdModel = np.zeros((1, 65), dtype=np.float64)
fgdModel = np.zeros((1, 65), dtype=np.float64)
rect = (60, 10, 400, 500)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = cv2.imread("37.jpg",0)
plt.subplot(121)
plt.imshow(mask2, cmap="gray")
plt.axis('off')
mask[mask2 == 0] = 0
mask[mask2 == 255] = 1
mask, bgd, fgd = cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
ogc = img * mask[:, :, np.newaxis]
plt.subplot(122)
plt.imshow(ogc, cmap="gray")
plt.axis('off')
plt.show()


运行之后,效果如下:


这里,我们构造了一个模板,并没有使用矩形框。通过模板,我们可以获取另一个图像中,大致的确定前景。这里,我们使用像素0标注确定背景,使用像素1标注确定前景。

相关文章
|
7月前
|
数据采集 存储 XML
深入浅出:基于Python的网络数据爬虫开发指南
【2月更文挑战第23天】 在数字时代,数据已成为新的石油。企业和个人都寻求通过各种手段获取互联网上的宝贵信息。本文将深入探讨网络爬虫的构建与优化,一种自动化工具,用于从网页上抓取并提取大量数据。我们将重点介绍Python语言中的相关库和技术,以及如何高效、合法地收集网络数据。文章不仅为初学者提供入门指导,也为有经验的开发者提供进阶技巧,确保读者能够在遵守网络伦理和法规的前提下,充分利用网络数据资源。
|
7月前
|
数据可视化 数据挖掘 UED
Python中的数据可视化:使用Matplotlib创建交互式图表
传统的数据可视化工具通常只能生成静态图表,而在数据分析和展示中,交互式图表能够提供更丰富的用户体验和更深入的数据探索。本文将介绍如何利用Python中的Matplotlib库创建交互式图表,让数据分析变得更加生动和直观。
|
1月前
|
数据可视化 JavaScript 前端开发
Python中交互式Matplotlib图表
【10月更文挑战第20天】Matplotlib 是 Python 中最常用的绘图库之一,但默认生成的图表是静态的。通过结合 mpld3 库,可以轻松创建交互式图表,提升数据可视化效果。本文介绍了如何使用 mpld3 在 Python 中创建交互式散点图、折线图和直方图,并提供了详细的代码示例和安装方法。通过添加插件,可以实现缩放、平移和鼠标悬停显示数据标签等交互功能。希望本文能帮助读者掌握这一强大工具。
70 5
|
4月前
|
机器学习/深度学习 XML 搜索推荐
图像自动化保存工具:Python脚本开发指南
图像自动化保存工具:Python脚本开发指南
|
7月前
|
Python
如何使用Python的Plotly库创建交互式图表?
Plotly是Python的交互式图表库,支持多种图表类型,如折线图、散点图、柱状图。使用步骤包括安装库、导入模块、准备数据、创建图表对象、添加数据和设置属性,最后显示或保存图表。
73 6
|
7月前
|
JSON JavaScript 数据可视化
数据可视化:将Python的Pandas与Vue结合展示交互式图表
【4月更文挑战第10天】本文探讨了如何利用Python的Pandas库和前端框架Vue.js创建交互式数据可视化应用。通过Pandas进行数据处理和分析,Vue.js构建用户界面,结合两者可实现动态图表展示。步骤包括数据准备、转换为JSON、创建Vue项目、发送数据请求、渲染图表、添加交互性和优化性能。这种结合为数据理解和探索提供了高效、用户友好的解决方案,适应于数据爱好者和专家,预示着未来数据可视化将更智能、互动。
343 1
|
7月前
|
Python
如何使用Python的Plotly库创建交互式图表?
Plotly是Python的交互式图表库,支持多种图表类型。安装Plotly后,导入graph_objects和express模块。准备数据,然后使用Figure()或px.line()创建图表对象。通过add_trace()添加数据,设置属性,并用show()或write_html()展示或保存图表。以下是一个创建交互式折线图的简单示例,展示了数据准备、对象创建、属性设置及显示过程。Plotly还支持高级功能如子图、多轴和动画,适用于复杂需求。
44 0
|
7月前
|
自然语言处理 数据可视化 Python
python主题建模可视化LDA和T-SNE交互式可视化
python主题建模可视化LDA和T-SNE交互式可视化
|
7月前
|
机器学习/深度学习 人工智能 IDE
Python是一种高级、解释型、交互式和面向对象的脚本语言
Python是一种高级、解释型、交互式和面向对象的脚本语言
72 2
|
数据采集 JavaScript 前端开发
Web爬虫开发指南:使用Python的BeautifulSoup和Requests库
Web爬虫是一种从互联网上获取数据的自动化工具,它可以用于抓取网页内容、提取信息和分析数据。Python提供了一些强大的库,其中BeautifulSoup和Requests是两个常用的工具,用于解析HTML内容和发起HTTP请求。本文将介绍如何使用BeautifulSoup和Requests库构建一个简单而有效的Web爬虫。