A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

内容来自OpenCV-Python Tutorials 自己翻译整理

目标:

GrabCut算法原理与应用
创建交互式程序完成前景提取

原理:
首先用矩形将要选择的前景区域选定,其中前景区域应该完全包含在矩形框当中。然后算法进行迭代式分割,知道达到效果最佳。但是有时分割结果不好,例如前景当成背景,背景当成前景。测试需要用户修改。用户只需要在非前景区域用鼠标划一下即可。
如文档中的图片,运动员和足球被蓝色矩形保卫,其中有数个用白色标记修改的,表示前景区域,黑色表示背景区域。

首先,输入矩形框,矩形框外部区域都是背景。内部一定包含前景。

电脑对输入图像进行初始化,标记前景和背景的像素。

使用高斯混合模型(GMM)对前景和背景建模。

根据输入,GMM会学习并创建新的像素分布。对未知的像素(前景或背景不确定),根据他们与已知的分类像素关系进行分类。(类似聚类操作)

这样会根据像素的分布创建一幅图,图中节点是像素。除了像素点是节点以外,还有Source_node和Sink_node两个节点。所有的前景图像斗鱼Source_node相连。背景与Sink_node相连。

像素是否连接到Source_node/end_node依赖于权值,这个权值由像素属于同一类,也就是前景或者背景的概率来决定。如果像素的颜色有很大区别,那么他们之间的权重就很小。

使用mincut算法对图像进行分割。它会根据最小代价方程对图像分成source_node和sink_node。代价方程是指裁剪所有边上权重的和。裁剪完成后,所有连接到source_node的判定为前景,sink_node上的为背景。

继续此过程,直到分类收敛。

此网站有关于GrabCut算法的详细讲解

示例:

cv2.grabCut()函数参数

img 输入图像

mask 蒙板图像,确定前景区域,背景区域,不确定区域,可以设置为cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD,也可以输入0,1,2,3

rect 前景的矩形,格式为(x,y,w,h),分别为左上角坐标和宽度,高度

bdgModel, fgdModel 算法内部是用的数组,只需要创建两个大小为(1,65)np.float64的数组。

iterCount 迭代次数

mode cv2.GC_INIT_WITH_RECT 或 cv2.GC_INIT_WITH_MASK,使用矩阵模式还是蒙板模式。

import numpy as np

import cv2

from matplotlib import pyplot as plt



img = cv2.imread('1.jpg')

mask = np.zeros(img.shape[:2],np.uint8)

bgdModel = np.zeros((1,65),np.float64)

fgdModel = np.zeros((1,65),np.float64)

rect = (50,50,450,290)#划定区域

cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)#函数返回值为mask,bgdModel,fgdModel

mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')#0和2做背景


img = img*mask2[:,:,np.newaxis]#使用蒙板来获取前景区域




cv2.imshow('p',img)

cv2.waitKey(0)

计算完成后mask里面值为0到3,其中0表示背景,1表示前景,2表示可能是背景,3表示可能是前景
代码中将0和2合并为背景 1和3合并为前景

样例中的图片结果如下

可以看到得到的结果并不准确,现在在这幅图片得到的蒙板上面添加标记,用白色(像素值为0)标记前景,黑色(像素值为255)标记背景。再次进行迭代计算,最后得到不错的结果

样例中的图片如下


5 个回复

倒序浏览
奈斯,优秀
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马