本文是一篇使用OpenCV实现patchmatch算法的笔记,实现环境为Visual Studio 2015 x64 + OpenCV 3.0。笔者并没有很多CV方面的经验,所以对算法的解释可能使用不规范的词汇,望各位指正谅解。
patchmatch算法的核心目的是在两张图片之间快速寻找对应的小区域。在应用上,patchmatch算法可以结合图像重组等技术,来实现诸如图像修复、图片融合、去水印等功能。Adobe Photoshop CS5之后提供的修复画刷、内容感知移动功能就是基于patchmatch算法实现的。
详情可戳 http://v.youku.com/v_show/id_XMTIxOTgyNTcy.html
墙外可戳 https://www.youtube.com/watch?v=fMe19oTz6vk
1.Patchmatch的概念
1.1 我们要做什么
patchmatch中的“patch”指的就是图片的一个小区域。具体在此算法中,一个patch是图片的一个3x3或5x5的小正方形区域。patchmatch顾名思义也就是对两张图片的对应patch完成匹配。以下我们称最终要进行处理的图为“目标图”,提供完整信息的图为“参考图”,并假设目标图与参考图的长宽是一致的。
1.2 相似度的定义
如何算是一个成功的匹配呢?很简单,对于图片A的一个patch,我们只需要找到图片B中与之“距离”最近/“相似度”最高的patch就可以了。所以这里我们需要对patch的距离/相似度加以定义。
在这个Demo中笔者使用负的“绝对距离”(各项直接相减、取绝对值、求和)作为相似性量度。
double sim_abs_diff(Mat& a, Mat& b, int _) {
// 此处int是为了函数签名一致性加的,实际无用
Mat tmp;
absdiff(a, b, tmp);
return 1e4 - sum(sum(tmp))[0];
}
1.3 偏移量
由于参考图与目标图的长宽是一致的,所以两个点a,b之间的偏移量就等于b-a(注意,a和b是两个向量)。对于目标图中所有的patch区域,我们要在参考图中找一个对应的patch匹配。我们使用一个三维数组记录这一匹配,数组中存储的是目标图到参考图各个patch的偏移量。为了避免多维数组传参的麻烦事,我们使用标准库中的vector来完成。
typedef vector< vector < vector <int> > > Vector3i; // 定义三维vector类型
Vector3i f; f.resize(n_row