网址:https://www.codeproject.com/Articles/99457/Edge-Based-Template-Matching
其算法思路与流程,在网址下方也有说明。以下为个人配合其说明与源码的一些理解。
可以下载到,src和demo两个文件包。
其中demo是需要opencv2.0的库才可以运行。
打开GeoMatch_src工程,工程版本实在太老了。只能强制升级到高版本的工程文件。
此时工程属性也是缺失环境的。在解决方案管理器中右键属性-》清除掉依赖的opencv库,然后替换上自己的opencv环境(注:必须是2.xx 版本的)我这里用的是64位的2.4.10
然后编译。正常通过了。
运行:
在这个位置把我抛出来了,看了下demo中的readme。
发现是通过外部传入字符串组调用的。
打开demo中的run,bat中可以找到具体调用的指令
其中最前面的 GeoMatch 是指运行“GeoMatch.exe”所以跳过。
为了方便测试在void WrongUsage();下插入以下代码
char*ppChar[12];
char*Param = "-t template.jpg -l 10 -h 100 -s search1.jpg -m 0.7 -g 0.9";
for (int i = 0; i < 12; i++)
{
ppChar[i] = new char[512];//测试用,懒得删
memset(ppChar[i], 0, 512);
int idx = 0;
while (*Param!=' ')
{
ppChar[i][idx++] = *Param++;
}
Param++;
}
CommandParser cp(12,ppChar); // object to parse command line
现在代码就可以正常跑了。
创建模板过程:
1.使用Sobel 获取8bit原图的x y 向一阶导(灰度变化速率) 并存储到16bit的图中。(此处为什么是16bit?)
2.获得每个点位置的梯度大小和方向的矩阵 (注:gx,gy 分别为某点上 的横向,纵向一阶导的值)
大小:Magnitude = Sqrt(gx^2 +gy^2)
方向:Direction = invtan (gy / gx) 再把方向规范化到 0,45,90,135 四个方向(此处的方向仅用作非极大值抑制)
3.对整图做非极大值抑制
详细:通过矢量方向,判断该矢量方向上的前后值是小于当前值。
eg: 方向为 45° 那么将会检查该像素 右上 左下 两个位置的值。如果当前值均大于该两个值,则保留。
4、滞后阈值处理
详细:
阈值《minContrast 移除该点
maxContrast》阈值》minContrast 其八邻域内无 任何点 大于 maxContrast 则移除该点。
阈值》maxContrast 直接保留该点
5.以数组的方式 记录成功保留的矢量数据 (x,y, gx,gy, 根号( 1/Magnitude) )(为什么使用根号,看匹配得分定义)
6.规范化中心,其中 中心位置为所有矢量x,y的均值。
由此,创建模板结束。
匹配部分
1.求目标图片x,y向一阶导(同创建)
2.求得梯度大小图片,matGradMag为存储梯度数据的图像.
(其大小,计数为 根号(1/(dx^2+dy^2))
)
3.滑窗匹配
得分:累计每个特征矢量对应位置的(Temp_gx*Img_gx )+(Temp_gy*Img_gy)*
( 1/(Temp_gx^2+Temp_gy^2) * 1/(Img_gx^2+Img_gy^2) )
其核心参考为,对应点位,dx,dy方向的综合梯度,是否与模板相近。
其中有个得分不足 判定,能够提早结束特征点遍历。
退出条件为:当前总得分《 min(贪心后得分和,理论最低得分和)
其中此处贪心值设置不合理。完全没用。
注意滑窗位置,以模板中心,从(0,0)开始滑,意味着窗口是超出目标图像区域的。
总结:
亮点1.使用了贪心值和不足分方式提前判定失败结果。
亮点2.匹配滑窗位置是以中心为基点匹配全图(得分图与原图大小一致)
问题1.太慢了!!!!!
问题2.x y向的梯度混淆了,使得匹配得分会整体偏高
问题3.未使用任何矢量,无法区分黑白。