交互式前景提取

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


然后看看GrabCut 算法的具体实现过程:

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

    经典图,,具体实现过程我就不不自量力了,,大致明白整个过程就行了。。我就在想就是我看懂了那莫名其妙的公式又有什么用呢,,,反正就是一个函数的事,,不是找借口哈。。

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

  • img 8位3通道的输入图像

  • mask 掩模图像 8位单通道。该参数用于确定前景区域,背景区域和不确定区域,可以设置4种形式。

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

  • rect 指包含前景对象的区域,该区域外的部分被认为是确定背景,前景一定要包含在rect指定的范围内,否则rect以外的前景部分就不会被提取出来。只有当参数mode 的值被设置为矩形模式 GC_INIT_WITH_RECT 时,参数rect 才有意义。格式为( x, y, w, h) 分别对区域左上角像素的坐标和区域的高度和宽度。如果前景位于右下方,又懒得判断原始图像的大小,对于 w h 可以直接用一个很大的数。使用掩模模式时,直接设置为none 就行。

  • bgdModel 为算法内部使用的数组,只需要创建大小为 (1 , 65) 的 numpy.float64数组

  • fgdModel 同上

  • iterCount 表示迭代的次数

  • mode 表示迭代模式

o = cv2.imread('fenge.jpg')
orgb=cv2.cvtColor(o,cv2.COLOR_BGR2RGB)
mask = np.zeros(o.shape[:2],np.uint8)          # 这里不使用掩模,就设置为0就行
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (50,80,190,250)                   # 这个矩形区域要根据自己的图来画。
cv2.grabCut(o,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')  # 一个判断是就是1 不是就是0
ogc = o*mask2[:,:,np.newaxis]           # 这个newaxis 就是新增一个维度,让掩模也变成三通道从(320,320)变成(320,320,1)
ogc=cv2.cvtColor(ogc,cv2.COLOR_BGR2RGB) # mask2 的值是1和0嘛,就是一个掩模,显示值为1 的部分
plt.subplot(121)
plt.imshow(orgb)
plt.axis('off')
plt.subplot(122)
plt.imshow(ogc)
plt.axis('off')


可以看见不用掩模时出来效果并不好,,头都被消去了。。我们可以对原图进行标注,将需要保留的部分设置为白色,将要删除的背景设置为黑色,以标记好的图像作为模板,使用函数进行提取。

  • 利用函数cv2.grabCut() 在cv2.GC_INIT_WITH_RECT 模式下对图像进行初步的前景提取,得到初步提取结构图像
  • 使用画图工具之类的,用白色笔刷在要提取的前景区域标记,黑色笔刷在删除的背景区域做标记。
  • 将当前设置好的图像另存为模板图像m0
  • 将模板图像中的白色值和黑色值映射到模板m 中,将模板图像m0 中的白色至(像素值为255)映射为模板图像m 中的确定前景(像素值为1) 将模板图像的黑色部分映射为模板图像中的确定背景(像素值为0)
  • 以模板图像作函数cv2.grabCut() 的模板参数,对图像完成前景提取。
  • 注意,画笔标记的模板图像m0 不能直接作参数mask 使用,grabCut() 要求mask的值必须是cv2.GC_BGD(确定背景)、cv2.GC_FGD(确定前景)、cv2.GC_PR_BGD(可能的背景)、cv2.GC_PR_FGD(可能的前景),或者是 0、1、 2、3 之中的值。所以要将模板图像m0 的白色黑色值映射到模板 m 上。
o= cv2.imread('fenge.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,80,190,250)
cv2.grabCut(o,mask,rect,bgd,fgd,5,cv2.GC_INIT_WITH_RECT)
mask2 = cv2.imread('fenge_mask.jpg',0)
mask2Show = cv2.imread('fenge_mask.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,2,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')


反正经过我多次尝试,,还是多涂点效果好,,不过这个算法明显就可以感觉到慢,,

在函数的实际使用中,可以不使用矩形初始化,直接使用模板模式,构造一个模板图像

  • 使用像素值 0 标注确定背景。
  • 使用像素值 1 标注确定前景。
  • 使用像素值 2 标注可能的背景。
  • 使用像素值 3 标注可能的前景。
    构建一个模板后,可以用于cv2.grabCut() 处理原始图像,即可完成前景的提取,,自定义模板的步骤为:
  • 使用 np.zeros() 构造一个像素值都是零的图像,后续逐步细化
  • 使用mask[30:512, 50:400]=3,将模板图像中第 30 行到第 512 行,第 50 列到 400 列的
    区域划分为可能的前景(像素值为 3,对应参数 mask 的含义为“可能的前景”)。
  • 使用 mask[50:300, 150:200]=1,将模板图像中第 50 行到第 300 行,第 150 列到第 200
    列的区域划分为确定前景(像素值为 1,对应参数 mask 的含义为“确定前景”)
o = cv2.imread('fenge.jpg')
orgb=cv2.cvtColor(o,cv2.COLOR_BGR2RGB)
mask2 = np.zeros(o.shape[:2],np.uint8)
bgd = np.zeros((1,65),np.float64)
fgd = np.zeros((1,65),np.float64)
mask2[50:320,60:270]=3 # 头像的可能区域
mask2[100:320,100:210]=1 # 头像的确定区域,如果不设置这个区域,头像的提取不完整
cv2.grabCut(o,mask2,None,bgd,fgd,5,cv2.GC_INIT_WITH_MASK)
mask2 = np.where((mask2==2)|(mask2==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')


这里构造的模板比较简单,如果构造更有针对性的模板,可以提取更为准确的前景对象,,不同图像需要构造不同的模板来划分他们的确定前景,确定背景,可能前景,可能背景,,看起来很麻烦。。不过这个效果是真的好,比自己随便画的强。。。

opencv入门:使用交互式进行前景提取相关推荐

  1. Python+OpenCV:交互式图像前景提取(Interactive Foreground Extraction using GrabCut Algorithm)

    Python+OpenCV:交互式图像前景提取(Interactive Foreground Extraction using GrabCut Algorithm) ################# ...

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

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

  3. 图像分割与提取:交互式前景提取(附OpenCV代码实现)

    一.简介 经典的前景提取技术主要使用纹理(颜色)信息,如魔术棒工具,或根据边缘(对比度)信息,如智能剪刀等完成.2004 年,微软研究院(剑桥)的 Rother 等人在论文 GrabCut: Inte ...

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

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

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

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

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

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

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

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

  8. opencv入门_【OpenCV入门之十八】通过形态学操作提取水平与垂直线

    小白导读 学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了[OpenCV入门]系列.新的一年文章的内容进行了很大的完善,主要是借鉴了更多大神的文章,希望让小伙伴更 ...

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

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

最新文章

  1. 模型可解释性技术概览
  2. 精华阅读第 10 期 |解开阿尔法狗(AlphaGo)人工智能的画皮
  3. PAT 1042. 字符统计
  4. React开发(148):componentWillReceiveProps
  5. [翻译:ASP.NET MVC 教程]理解模型、视图和控制器
  6. matlab最小生成树举例,Matlab最小生成树示例
  7. (6)DFS(深度优先搜索算法):n皇后问题
  8. Armadillo的安装
  9. BerkeleyDB
  10. xhEditor用法
  11. 心灵捕手影评,觉得很好。看一部好电影就像读一本好书。
  12. 网络延迟到底是什么东西?
  13. 区块链对广告行业发展的影响
  14. i5 12500H性能怎么样 相当于什么水平
  15. 算法系列之十九:用天文方法计算日月合朔(新月)
  16. mongodb数据库学习日记(一)
  17. mfc 多边形裁剪算法
  18. jquery遍历得到的 Map 数据,
  19. ATFX:新西兰联储加息50基点,NZDUSD先涨后跌
  20. 无法访问阿里云ECS实例运行网站的解决方法

热门文章

  1. 2019 下半年 Flutter 实现的性能优化 | 英雄榜
  2. 黑窗口下安装MySQL数据库
  3. 局域网联机_文明6/单机.局域网联机/5/4/3【单机游戏】
  4. java中jar包怎么下载
  5. Ansible配置文件ansible.cfg
  6. iPhone排水功能如何使用?如何利用快捷指令实现iPhone排水功能?
  7. WAR3改键工具FinalKey beta 1.0制作完成
  8. 全面支持 PyTorch 2.0:BladeDISC 5 月~11 月新功能发布
  9. 给asus eeepc 1015pw的 1301版本的 bios添加slic2.1
  10. FBEC2021 | 对话阿里巴巴云游戏事业部/元境副总经理 龙志勇:坚持研运一体化服务的路线