python+opencv图像处理,
GrabCut算法通常,我们需要图像将前景从背景中分离出来,有时可能我们只需要前景。在本教程中,我们将介绍用于交互式前景提取的GrabCut算法。
GrabCut是一种基于图切割的图像分割方法。GrabCut算法是基于图割算法的改进。
基于待分割对象的指定包围盒,使用高斯混合模型估计分割对象和背景的颜色分布(注意,图像分为两部分:分割对象和背景)。总之,该算法只需要确认前景和背景的输入,就可以完成前景和背景的最优分割。
该算法利用了图像中的纹理(颜色)信息和边界(对比度)信息,只需要少量的用户交互就可以得到较好的分割结果。与分水岭算法类似,但计算速度慢,得到的结果更准确。GrabCut算法是从静止图像中提取前景对象的最佳选择(例如,从一幅图像剪切到另一幅图像)。
原则上,我们使用RGB颜色空间,并使用K个高斯分量(其中一个K=5)的全协方差GMM(混合高斯模型)来对目标和背景建模。那么还有一个额外的向量k={k1,kn,kN},其中kN是第n个像素对应的高斯分量,kn {1,K}。对于每个像素,它来自目标GMM的高斯分量或背景GMM的高斯分量。
因此,用于整个图像的吉布斯能量是下面的等式7:
其中,U是地区术语。上一篇文章提到,你指的是像素被归类为目标或背景的惩罚,也就是像素属于目标或背景的概率的负对数。我们知道高斯混合密度模型具有以下形式:
所以取负对数后就变成了公式(9)的形式,其中有三个GMM的参数:每个高斯分量的权重,每个高斯分量的均值向量U(三个元素向量,因为RGB有三个通道)和协方差矩阵(33矩阵,因为RGB有三个通道)。如公式(10)。也就是说,描述目标的GMM和描述背景的GMM这三个参数需要通过学习来确定。一旦确定了这三个参数,那么在我们知道了一个像素的RGB颜色值之后,我们就可以代入目标的GMM和背景的GMM,就可以得到这个像素分别属于目标和背景的概率,也就是可以确定Gibbs能量的区域能量项,也就是可以计算出图的t-link的权重。那么如何求n-link的权重呢?也就是边界能量项v .怎么找?
边界项类似于图割,反映了相邻像素M和n之间不连续的惩罚,如果两个相邻像素之间的差异很小,则很可能属于同一目标或同一背景。如果差别很大,说明这两个像素很可能在目标和背景的边缘,所以分离的可能性比较大。因此,两个相邻像素之间的差异越大,能量越小。在RGB空间中,我们使用欧几里德距离(第二范数)来度量两个像素之间的相似性。这里的参数是由图像的对比度决定的。可以想象,如果图像的对比度较低,也就是说本身不同的像素M和N之间的差值还比较低 ZM-Zn ,那么我们就需要将这个差值乘以一个较大的。对于高对比度的图像,属于同一目标的像素M和N之间的差异可能仍然比较大 ZM-Zn 。这时候就可以得到我们想要的图了,我们就可以对它进行分割了。
我们来看一下具体的实现原理:(1)直接选择框内目标得到一个初始三分图T,即将框外的所有像素作为背景像素TB,而将框内的所有像素TU作为“可能目标”像素。
(2)对于TB中的每个像素n,初始化像素n=0的标签 n,该像素为背景像素;并且对于TU中的每个像素n,初始化像素n=1的标签 n,即作为“可能目标”的像素。
(3)经过以上两步,我们可以分别得到部分属于目标的像素(n=1)和其余属于背景的像素(n=0)。这时,我们可以通过这个像素来估计目标和背景的GMM。我们可以通过K-k-means算法将属于目标和背景的像素聚类成K类,即GMM中的K个高斯模型。此时,GMM中的每个高斯模型都有一些像素样本集,其参数均值和协方差可以通过它们的RGB值来估计,而高斯分量的权重可以通过属于高斯分量的像素数与总像素数的比值来确定。
OpenCV中的实现步骤:
1.定义图片中包含一个或多个对象的矩形。
2.矩形外的区域被自动视为背景
3.对于用户自定义的矩形区域,背景中的数据可以用来区分其中的前景和背景区域。
4.使用高斯混合模型对背景和前景进行建模,未定义的像素被标记为可能的前景或背景。
5.图像中的每个像素都被视为通过虚拟边缘与周围的像素相连,每个边缘都有一个属于前景或背景的概率,这个概率是基于它与周围颜色的相似性。
6.每个像素(即算法中的节点)将与前景或背景节点相链接。
7.节点链接后,如果节点之间的边属于不同的终端,那么它们之间的边会被切断,这样可以把图像的各个部分分开。
我们先来了解一下相关的函数API:
mask,b gdmodel,fgdmodel=cv2.grabcut (img,Mask,rect,b gdmodel,fgdmodel,itercount [,mode]) IMG:输入图像Mask:屏蔽图像,指定哪些区域是背景、前景或可能的背景/前景等它由以下徽标标记,2。佐治亚州BGD市,CV2。GC_FGD,CV2。BGD,CV2。GC_PR_FGD,或者简单地将0,1,2,3传递给图像。Rect:矩形的坐标,包含前景对象的格式(x,y,w,h)。h)bdgModel,fgdModel:算法内部使用的数组,只需要创建两个大小为(1,65)的np.float64 type 0数组。iterCount:算法运行的迭代次数。方式
:CV2。RECT或CV2。GC_INIT_WITH_MASK,或者一个组合来决定我们是画一个矩形还是最后一个接触点。img=cv2.imread(data.jpg )
img=cv2.resize(img,(224,224),插值=cv2。间_立方)
打印(图像形状)
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。RECT)
mask 2=NP . where((mask==2)(mask==0),0,1)。astype(uint8 )
img=img * mask2[:np.newaxis]
如果不是os.path.lexists(cut ):
os.makedirs(cut )
cv2.imwrite(cut/1.jpg ,img)
转载请联系作者获得授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。