Gointerface接口声明实现及作用详解
809
2022-08-27
python opencv图像处理算法之GrabCut算法(python编程)
GrabCut算法
通常情况下,我们需要图像进行前景后景进行分离,有的时候也许我们仅仅是需要前景。本次教程我们将介绍GrabCut算法进行交互式前景提取。
GrabCut是一种基于图切割的图像分割方法。GrabCut算法是基于Graph Cut算法的改进。
基于要被分割对象的指定边界框开始,使用高斯混合模型估计被分割对象和背景的颜色分布(注意,这里将图像分为被分割对象和背景两部分)。简而言之,就是只需确认前景和背景输入,该算法就可以完成前景和背景的最优分割。
该算法利用图像中纹理(颜色)信息和边界(反差)信息,只要少量的用户交互操作就可得到较好的分割效果,和分水岭算法比较相似,但计算速度比较慢,得到的结果比较精确。若从静态图像中提取前景物体(例如从一个图像剪切到另外一个图像),采用GrabCut算法是最好的选择。
原理
我们采用RGB颜色空间,分别用一个K个高斯分量(一取般K=5)的全协方差GMM(混合高斯模型)来对目标和背景进行建模。于是就存在一个额外的向量k = {k1, . . ., kn, . . ., kN},其中kn就是第n个像素对应于哪个高斯分量,kn∈ {1, . . . K}。对于每个像素,要不来自于目标GMM的某个高斯分量,要不就来自于背景GMM的某个高斯分量。所以用于整个图像的Gibbs能量为下图式子7:
我们来看看具体的实现原理:
(1)通过直接框选目标来得到一个初始的trimap T,即方框外的像素全部作为背景像素TB,而方框内TU的像素全部作为“可能是目标”的像素。
(2)对TB内的每一像素n,初始化像素n的标签αn=0,即为背景像素;而对TU内的每个像素n,初始化像素n的标签αn=1,即作为“可能是目标”的像素。
(3)经过上面两个步骤,我们就可以分别得到属于目标(αn=1)的一些像素,剩下的为属于背景(αn=0)的像素,这时候,我们就可以通过这个像素来估计目标和背景的GMM了。我们可以通过k-mean算法分别把属于目标和背景的像素聚类为K类,即GMM中的K个高斯模型,这时候GMM中每个高斯模型就具有了一些像素样本集,这时候它的参数均值和协方差就可以通过他们的RGB值估计得到,而该高斯分量的权值可以通过属于该高斯分量的像素个数与总的像素个数的比值来确定。
OpenCV中的使用
实现步骤:
1.在图片中定义含有(一个或者多个)物体的矩形
2.矩形外的区域被自动认为是背景
3.对于用户定义的矩形区域,可用背景中的数据来区别它里面的前景和背景区域
4.用高斯混合模型来对背景和前景建模,并将未定义的像素标记为可能的前景或背景
5.图像中的每一个像素都被看作通过虚拟边与周围像素相连接,而每条边都有一个属于前景或背景的概率,这基于它与周围颜色上的相似性
6.每一个像素(即算法中的节点)会与一个前景或背景节点链接
7.在节点完成链接后,若节点之间的边属于不同终端,则会切断它们之间的边,这就能将图像各部分分割出来
先来了解相关的函数API:
mask, bgdModel, fgdModel = CV2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode])
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类型的0数组.iterCount :算法运行的迭代次数.mode:CV2.GC_INIT_WITH_RECT或CV2.GC_INIT_WITH_MASK,或者组合起来决定我们是画矩形还是最后的触点.
img = cv2.imread('data.jpg') img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_CUBIC) print(img.shape) mask = np.zeros(img.shape[:2], np.uint8) bgdModel = np.zeros((1, 65), np.float64) fgdModel = np.zeros((1, 65), np.float64) rect = (10,10,224,224) cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8') img = img * mask2[:, :, np.newaxis] if not os.path.lexists('cut'): os.makedirs('cut') cv2.imwrite('cut/1.jpg', img)
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~