GraphCut——GrabCut

GraphCut——GrabCut,第1张

此种算法是对图像进行分割 *** 作,其将一幅图像转换成图形结构来描述,通过找到图中的最小割,从而将图像中的前景背景进行分割。

1、GraphCut

如上图所示,将图中的像素点作为图中的点集,相邻像素通过边相连,另外多出的两个点S,T分别代表的是归于前景的点和归于背景的点。对每个边设置相应的权重,图割的目的就在于利用最小割的方法将边缘部分进行分割,此时的能量值(损失值)最小,由此得到对应的S,T集合,达到分割的目的。过程如下图所示(其中B,O代表事先设置的种子点,由此知道分割出来的部分哪个代表背景,哪个代表目标;B代表该点属于背景点,O代表该点属于目标点):

2、GrabCut:

GrabCut是基于GraphCut的改进算法,通过交互的方式得出前景与背景。

为什么画个框就能分割出前景与背景呢?

在框选出区域后,则将选框以外的部分视为背景区域,将选框以内的区域视为可能的前景区域。然后通过计算前景高斯混合模型(GMM)和背景GMM,然后对每一个像素的rgb值代入单个的高斯模型进行计算,选取值最大的那个模型作为该像素点的归属,然后再建立一个图,对该图求解最小割,如此循环直至收敛,由此判断得出选框内的前景区域与背景区域。

那关键在于如何得出前景与背景的GMM呢?

不同于GraphCut中的一次性求解图的最小割问题,GrabCut中采用的是迭代优化的方式逐步求解得出GMM。其具体过程如下图所示:·

*其实对于这两个算法的具体实现并不是很清楚,在这儿只是想大体了解有这样的一种分割的算法,故也就不深究其是如何具体实现的了~另外Opencv中已经实现了GrabCut算法,可以去玩玩~~

的确玩了一回,在进行区域分割的时候,通过将图像进行二值化处理后,将其作为掩模来进行grabcut *** 作。但是处理速度比较慢,并且分割的准确性主要依赖二值图像的质量~。

最近接了个抠图的功能,要求像这样子让用户把轮廓圈一下,把前景抠出来。这里用的是OpenCV的GrabCut算法。

传入的img是原图(CV_8UC3格式),mask是用户标记的前景和背景信息(矩阵中只含以上四种取值),rect是用户选中的感兴趣区域(ROI),bgdModel和fgdModel是临时数组(对同一张图片进行编辑时不要修改),iterCount是迭代次数,mode是运行模式(初始化或者不是初始化)。

总之,就是要用cv::GC_INIT_WITH_MASK模式去初始化,传入原图和用户圈出来的轮廓图。

用户圈完轮廓之后,用cv::findContours()生成一张类似这样的图。轮廓外部标记为已知背景,轮廓内部标记为已知前景,轮廓标记为未知。

初始化完之后,将mask和1做与,然后将原图copyTo一下,就能得到抠出来的图片。

第一次出来的结果可能会有些地方没分好,这时候用户再手动标记一下,用cv::GC_EVAL继续运行就好了。

Win10的画图3D有个神奇选择功能,就是grabCut算法这个流程的,要先框出ROI,有兴趣的可以尝试一下。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11216854.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存