模板匹配(Template Matching)是图像识别中最具代表性的方法之一。它从待识别图像中提取若干特征向量与模板对应的特征向量进行比较,计算图像与模板特征向量之间的距离,用最小距离法判定所属类别。模板匹配通常事先建立好标准模板库。
在工作过程中遇到一个判断样本距离的方法,先把他记录如下:
循环计算待测样本和训练集中已知样本之间的距离,比较所有的距离值,找出与待测样本最近的已知样品,其中所对应的样本所属的类别就是待测样本X所属的类别。
c实现代码如下:
/****************************************
*参数:
* src:待匹配特征向量
* template:模板向量
*返回值:
* int:返回匹配结果;-1:无匹配项
*意义:
* 输入待匹配特征向量,输出匹配结果
*****************************************/
#define NFeature 25 //特征个数
#define NSample 10 //样本个数
int templateMatching(double src[], double template[][NFeature])
{
double d[11] = {0.0}, temp, mind = 10.0; //匹配度
int flag = -1, i, j;
for(j = 0; j < NSample; j++) {
for(i = 0; i < NFeature; i++) {
temp = pow(src[i] - template[j][i], 2);
d[j] += temp;
}
d[j] = sqrt(d[j]);
if(mind > d[j]) {
mind = d[j];
flag = j;
}
}
return flag;
}
不足之处
以上算法有一个很大的问题,就是当特征向量值顺序改变之后,计算结果有很大的变化。例如:
B = {1, 2, 3, 4}; A1 = {4, 3, 2, 1}; A2 = {1,2,3,4}。A1与B匹配,结果为{3*3+1*1+1*1+3*3} = 20;A2与B匹配,结果为{0+0+0+0} = 0;很明显特征向量A1与A2是相同的,在实际图像识别过程中有可能造成:一个图像旋转了一定角度,就无法识别出来。所以,这个算法只适合同方向的物体匹配,例如车牌字符识别等。
总结:
1. 只适合恒定方向特征匹配,例如车牌中的字符特征匹配
Hausdorff是描述两组点之间相似程度的一种度量,它是集合和集合之间距离的一种定义形式。下面我们慢慢讲解Hausdorff算法的过程。
- 点到点集的距离
- A集合到B集合的直接Hausdorff距离
还是以上面的例子为例来说明。例如:B = {1, 2, 3, 4}, A1 = {4, 3, 2, 1}, A2 = {1 ,2, 3, 4};A1与B匹配:Max{0, 0} = 0; A2与B的匹配:Max{0, 0} = 0;可以看到匹配的结果是:A1与A2是相同的,即使他们特征元素的顺序打乱了。一样可以把他们都正确匹配出来。
如图所示,X1、X2与T是一样的特征向量,只是顺序打乱了,但是匹配都是0;匹配效果还是很好的。X3是随机生成的其他的特征向量。
代码:
下面按照最一般的情况,计算待测特征向量X与某一样本T的匹配度。特征元素为有理数。
/*******************************************************
*参数:
X:输入特征向量数组
T:模板库中某一样本特征向量
n: 特征向量个数
返回值:
返回匹配结果
函数意义:
通过输入待测特征向量和模板特征向量,计算出待测特征向量
的匹配度,数值越小,匹配程度越高。式中的距离范式是特征元素
之间的差值绝对值。
***************************************************/
double charrecognize(double X[], double T[], int n)
{
int i,j;
double d[2] = {0.0};//存储X-->T的Hausdorff和T-->X的Hausdorff值
double minTemp = 1000.0, sum;
//计算X-->T的Hausdoff值
for(i = 0; i < n; i++) {
minTemp = 1000.0;
for(j = 0; j < n; j++) {
sum = fabs(X[i] - T[j]);
if(sum < minTemp)
minTemp = sum;
}
d[0] += minTemp;
}
//计算T-->X的Hausdorff值
for(j = 0; j < n; j++) {
minTemp = 1000.0;
for(i = 0; i < n; i++) {
sum = fabs(T[j] - X[i]);
if(sum < minTemp)
minTemp = sum;
}
d[1] += minTemp;
}
//返回较大值
if(d[0] > d[1])
return d[0];
return d[1];
}
当我们匹配要求特定方向、特定位置的图片时,其实也可以用Hausdorff距离进行特征匹配。
如图所示,第一幅图是模板图片,后面都是要与模板进行匹配的图像。
三幅图像虽然是一样的,只是位置和角度偏移了一些,出现的结果偏差却很大。这并非说明Hausdorff距离算法性能不佳,只是上述实验中的“特征选择”限定了Hausdorff距离算法对偏移和旋转过于敏感,也正是因为有了这种敏感,也更容易区分“非匹配项”。当我们图像特征限定在某一方向和位置时,Hausdorff将表现出优异的区分性能。例如:字符模板限定在“字符重心在图片重心,不旋转”,待测样本也如此限定。
代码流程
取D = Max{D(X, T), D(T, X)},作为匹配的结果。
/****************************************
参数:
X:样本二值图,只包含特征信息
T:模板二值图,只包含特征信息
返回值:
double:返回匹配度,越低越匹配
意义:
以样本二值图特征像素坐标作为特征点进行
匹配。
*****************************************/
double charrecognise(Mat X, Mat T)
{
int i, j, m, n;
double distemp = 5.0, distemp1, distsum, distsum1;
//样本到模板的距离
distsum = 0.0;
for(i = 0; i < X.cols; i++) {
for(j = 0; j < X.rows; j++) {
if(X.at(i, j) == 255) {
distemp = 5.0;
for(m = i - 3; m <= i + 3; m++) {
for(n = j - 3; n <= j + 3; n++) {
if(m < 0) m = 0;
if(m > X.cols) m = X.cols;
if(n < 0) n = 0;
if(n > X.rows) n = X.rows;
if(T.at(m, n) == 255) {
distemp1 = sqrt(pow((double)m - i, 2) + pow((double)n - j, 2));
if(distemp1 < distemp) distemp = distemp1;
}
}
}
}
distsum += distemp;
}
}
//模板到样本的距离
distsum1 = 0.0;
for(i = 0; i < T.cols; i++) {
for(j = 0; j < T.rows; j++) {
if(T.at(i, j) == 255) {
distemp = 5.0;
for(m = i - 3; m <= i + 3; m++) {
for(n = j - 3; n <= j + 3; n++) {
if(m < 0) m = 0;
if(m > T.cols) m = T.cols;
if(n < 0) n = 0;
if(n > T.rows) n = T.rows;
if(X.at(m, n) == 255) {
distemp1 = sqrt(pow((double)m - i, 2) + pow((double)n - j, 2));
if(distemp1 < distemp) distemp = distemp1;
}
}
}
distsum1 += distemp;
}
}
}
if(distsum > distsum1)
return distsum;
return distsum1;
}
总结