LazySnapping 算法
简介
这是一篇和GrabCut同时期的算法,论文名称就叫《Lazy Snapping》,他的作用是用户交互指定前景背景来分割,如图所示。
我还是使用的Eigen库+maxflow库实现,代码库链接如下:MaxtirError/LazySnaping: LazySnaping algorithm with pure C++ and Qt GUI (github.com)
这篇文章仍然用到了两个简单的前置算法:分水岭算法和k-means聚类,下面简单介绍
分水岭算法
这个算法被用于图像预分割,想法非常巧妙。首先,图像转灰度,其次,把灰度看成高度,那么整张图片形成了一张地形图,尝试把水注入地形图中,当两块水域合并的时候,修筑堤坝,分割这两块小区域。实际上就是以每个局部极小值为中心把图像分割成若干块。
我并没有去阅读这个算法的原论文,而是基于上面的想法写了如下算法。
-
图像转灰度图
-
从小到大扫描灰度,对于扫描到的新点 u u u,考虑和他四相邻的节点 v i v_i vi:
-
对于已经被扫描过且满足 G r a y ( u ) − G r a y ( v ) < = t h r e d ( 20 ) Gray(u)-Gray(v)<=thred(20) Gray(u)−Gray(v)<=thred(20)的 v i v_i vi,直接把这个新点 u u u划分到随便一个 v i v_i vi所在区域。
-
如果不存在这样的 v i v_i vi,把 u u u划分到一个新的区域
扫描完所有灰度之后,可以得到一个划分。
如下是某张图划分的结果
原图:
分水岭算法:
可以看到,很多相似的像素区域(比如天空)被很好地划分了。
这个算法最显著的效果就是:优化了参数空间。
原图大小是960*720,优化过后的region只有32298,只有原图的4%左右
k-means聚类
类似GMM的一个聚类算法,但是比GMM简单很多。输入是一堆数据 { X i } \{X_i\} { Xi},希望找到一个大小为k的划分 { S 1 ⋯ S k } \{S_1\cdots S_k\} { S1⋯Sk},使得 E n e r g y = ∑ k ∑ X i ∈ S k ∣ ∣ X i − μ k ∣ ∣ Energy=\sum_k \sum_{X_i\in S_k} ||X_i-\mu_k|| En