抠图算法(一) - Shared Sampling for Real-Time Alpha Matting (2010)

论文引用:

Shared Sampling for Real-Time Alpha Matting
Eduardo S. L. Gastal and Manuel M. Oliveira
Computer Graphics Forum. Volume 29 (2010), Number 2.
Proceedings of Eurographics 2010, pp. 575-584.

1. 序言

这篇论文的入门学习是通过这篇博客: 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting: , 熟悉了其中的大致原理之后才到原文中深入研究. 感谢 Imageshop 大神的博客专栏: https://www.cnblogs.com/Imageshop, 在这里学到了很多, 希望跟随大神的脚步不断成长.

关于这篇论文, 有一个专门的主页: http://www.inf.ufrgs.br/~eslgastal/SharedMatting/, 其中包含了论文 pdf 下载和论文中使用的数据集的下载, github 中有实现代码: https://github.com/np-csu/AlphaMatting.

论文的标题简单粗暴, 实时性是最大的亮点. 但是论文中也重点说明其实时性的前提条件是:

  • 必须依赖于 GPU 的并行编程优化;

另外一个限制是针对算法本身的. 在总结部分会详细说明.

2. 算法细节

接下来根据论文的结构依次描述.

总的来说, 这篇文章还是属于 Alpha Matting 的范畴. 因此这篇文章要解决的问题依然是 Alpha Matting 的经典方程:

(1) C p = α p F p + ( 1 α p ) B p

式中: C p 是我们观察到的图像的颜色,式子右侧的左右变量: α p , F p , B p 均是未知量,分别表示 未知区域 的透明度, 前景及背景.

鉴于未知量数目过多, 必须增加一些附加的约束才能求解这个方程. 常用的约束是是: (1) 和源图像大小相同的 TriMap 图; (2) 用户手工画出的草图形式.
如下两图所示:

这里写图片描述

TriMap 图像的像素数据类型为 int 型, 如未特别说明,一般白色部分表示前景,黑色表示背景,灰色表示待识别的部分.

论文中提到, 在 2010 年前后解决 matting 问题的主要方法是基于 sampling, pixel affinities 或者两者的结合( sampling + pixel affinities),特别是 pixel affinities 和 两者的结合( sampling + pixel affinities) 是主流的方式。local affinities 被用在求解或 refine matte 图.

但是这两种都需要求解一个大型的线性系统,这个系统的大小和未知区域的像素点个数成正比, 因此对于 1MB 左右大小的图,求解时间在几秒到几分钟不等。

TODO: 这篇论文提出的算法应该说是基于 sampling 技术的,他充分利用了相邻像素之间的相似性,并利用了算法内在的并行性,结合 GPU 编程,实现抠图的实时展示。

另外, 论文中反复提到的一个前提: 在一个小的邻域内的像素值的 ( α , F , B ) 值是相似的.

TriMap scribbles

这样的约束条件使得我们知道了那一部分是明确属于前景(α p =1),而那一部分是属于背景(α p =0),那么下面的主要任务就是搞定那些未知区域的α p 值 。

 总的来说,论文提出的算法可以分成4个步骤:

 第一步:Expansion,针对用户的输入,对已知区域(前景或背景)进行小规模的扩展;

 第二步:Sample and Gather,对剩余的未知区域内的每个点按一定的规则取样,并选择出最佳的一对前景和背景取样点;

 第三步:Refinement,在一定的领域范围内,对未知区域内的每个点的最佳配对重新进行组合。 

 第四步:Local Smoothing,对得到的前景和背景对以及透明度值进行局部平滑,以减少噪音。

2.1 Expansion

   这一步,按照我的经验,可以不做,他唯一的作用就是减少未知点的个数,可能在一定程度上减小后期的计算量,原理也很简单,就是对一个未知点,在其一定的邻域半径内(文中推荐值10,

并且是圆形半径),如果有已知的背景点或前景点,则计算其颜色和这些已知点颜色的距离,然后把这个未知点归属于和其颜色距离小于某个值并且最靠近该点的对象(前景或背景)。

在CSDN提供的参考代码中,这一部分的编码其实写的还是很有特色的,他的循环方式不同于我们普通的邻域编码,他是从像素点逐渐向外部循环开来,有点类似左图的这种循环方式(实际上还是有点区别的,实际是上下两行一起处理,在左右两列处理,然后再向外层扩散),这种处理方式的明显好处就是,只要找到某个点颜色距离小于设定的值,就可以停止循环了,因为这个点肯定是第一个符合颜色距离条件又同时符合物理距离最小的要求的。

这一步做不做,最最终的结果又一定的影响,但是他不具有质的影响。

2.2 Sample and Gather

  总的来说,这一步是算法的核心部分,也是对结果影响最大的,他的步骤说起来其实也很简单,我们先看下图。

 在这个图中,P和q点都是未知区域,我们需要通过一定的原则在已知区域为其取得一定的样本对,论文中提出的提取方法是: 
设定一个参数Kg,其意义为一个点最多可能取样的前景点和背景点的个数,也就意味着最多的取样对为Kg*Kg组,通常这个值可以取为4或者更多,论文建议取4就可以了,越大则程序越耗时。

 这样对于每个未知点,从该点出发,引出Kg条路径,每个路径之间成360/Kg的夹角,记录下每条路径经过的路线中首次遇到的前景或背景点,直到超出图像的边缘。

 为了算法的稳定性,每3*3的矩形区域内(4*4或者5*5也没说不可以的),路径的起始角度周期性的改变,这样相邻像素的Kg条路径经过的区域就有着较大的不同能得到更为有效的结果集。

由上图可以看到,在不少情况下,未知点的前景和背景取样数并不能达到Kg个,甚至极端情况下,找不到任何一个取样点,这样该点就无法进行透明度的计算了,这就要靠后面的过程了。  

前景取样点数量分布 背景取样点数量分布 前景+背景取样点数量分布

上图绘制了前面列举的TriMap图中未知区域每个部位的取样点数量分布情况,颜色越靠近白色,表明取样点的数量越大,从图中可以明显看出,处于图像角落的一些未知点取样情况并不是特别理想,但基本上未出现没有取到样的情况,那我们在来看看scribbles那张图的结果。

前景取样点数量分布 背景取样点数量分布 前景+背景取样点数量分布

特别是前景取样分布的结果似乎不太令人满意,有些部分取样数为0了,这个问题下面还会谈到。

 在完成取样计算后,我们就需要找出这些取样点中那些是最佳的组合,这个时候就涉及到一般优化时常谈到的目标函数了,在这篇论文中,对目标函数用了四个小函数的乘积来计算,分别如下:

1:

其中

为了全面,我们将上式中α p 的计算公式列出:

公式(2)的道理很为明显,用一对F/B算出的α值如果很合理的话,那么用α结合F/B重新计算出的颜色应该和原始颜色的差距很小。公式(3)在表明在一定的领域内,由于像素一般不会有突变,差值的平均值也应该很小。

  为方便理解,我贴出计算α的部分代码:

///
/// 通过当前点、前景点以及背景点的颜色值计算对应的Alpha值,对应论文的公式(12)。
///
/// 当前点的BGR颜色分量值。
/// 前景点的BGR颜色分量值。
/// 背景点的BGR颜色分量值。
/// Alpha会出现不在[0,1]区间的情况,因此需要抑制。
double CalcAlpha(int BC, int GC, int RC, int BF, int GF, int RF, int BB, int GB, int RB)
{
double Alpha =(double) ((BC - BB) * (BF - BB) + (GC - GB) * (GF - GB) + (RC - RB) * (RF - RB)) /
((BF - BB) * (BF - BB) + (GF - GB) * (GF - GB) + (RF - RB) * (RF - RB) + 0.0000001); // 这里0.0000001换成Eps在LocalSmooth阶段似乎就不对了,有反常的噪点产生
if (Alpha > 1)
Alpha = 1;
else if (Alpha < 0)
Alpha = 0;
return Alpha;
}
2: 作者考虑在未知点到取样的前景和背景点之间的直线路径上,应该尽量要少有像素的突变,比如如果这条路径需要经过图像的边缘区域,则应该设计一个函数使得该函数的返回值较大,于是作者使用了下面的公式:

上式即沿着路径对像素颜色进行积分,离散化后也就是一些累加,CSDN的提供的代码在这个函数的处理过程中是有错误的,因为他最后一个判断条件使得循环只会进行一次,有兴趣的朋友可以自己去改改。

 按照公式(4)的意义,一个未知点属于前景的可能性可由下式表示:

        、

 而一个好的组合也应该最小化下式:

3、未知点和前景点之间的物理距离,一个好的组合中的前景点应该要尽量靠近未知点;

4、未知点和背景点之间的物理距离,一个好的组合中的背景点也应该要尽量靠近未知点;

将这四个条件组合起来,最终得到如下的目标函数:

各子项的指数数据可详见论文本身。

 按照这个要求,对前面进行取样得到数据进行处理,并记录下使上式最小的那一对组合,就初步确定了最佳的取样点。

 其实,这个时候我们也就可以初步获得处理后的α值了,比如对于我们前面所说的Trimap,其原始图像及经过sample和gather处理后的结果如下图:

从处理结果看,已经可以粗略的得到处理的效果了。

2.3、Refinement

初步的gather处理后,正如前文所说,得到的结果还不够细腻,并且有些未知点由于采样的过程未收集到有效的前景和背景数据,造成该点无法进行处理,因此,在Refinement阶段需要进一步解决这个问题。

  论文提出,首先,在一定的邻域内,比如半径为5的领域内,首先统计出公式(2)对应的MP值最小的3个点相关颜色数据,并对这些数据进行加权平均,得到数据对:       



   然后按照下面这些公式计算新的前景、背景、透明度及可信度的计算。

可信度的计算是为下一步的局部平滑做准备的,他反应了我们在这一步确定的取样点是否合理程度的一个度量,经由此步骤,我们可得到的透明度和合成图如下所示:

可见在这一步得到的结果对于上图来说已经相当完美了。

2.4 Local Smoothing

这一步说实在的我没有花太多的精力去看,他的实现过程大概有点类似于高斯模糊,但里面多了很多其他方面的处理,一个很好的事情就是在CSDN提供的代码中对这部分每个公式的实现都是正确的,也是完整的,因此,有兴趣的朋友需要自己多看下论文和对应的代码了。

三、算法的效果

按照论文提供的相关资料集我自己搜集的一些图及配套的Trimap测试了该算法的一些结果,现贴出如下所示:

总结

另外一个限制是针对算法本身的. 因为文中提出的算法是以一个假设为前提展开的, 也就是假设未知区域的前景色和背景色可以通过分析其领域像素来显式估计出来. 因此, 对于那些前景完全透明, 或前景色和背景色存在严重重叠的图片就会出现问题.

参考资料

[1]. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting

猜你喜欢

转载自blog.csdn.net/gzj2013/article/details/82685389
今日推荐