最近做实验要用到SIFT特征,关于SIFT特征的细节这里不再详述,可以参考:http://blog.csdn.net/abcjennifer/article/details/7639681/
这里着重讲解一下关于SIFT特征匹配时需要用到的一种量化方法--乘积量化。
由于SIFT特征匹配时主要用到的是描述子信息,而该描述子信息的维度比较高,因此在局部特征匹配时计算较为复杂,因此需要量化为视觉词汇(visualword)。
首先SIFT特征量化时需要的两个工具:1.SIFT特征提取(有开源代码)。2.视觉词典(需要自己聚类学习)。
有了这两个工具就可以开始量化操作。
首先使用SIFT算法提取局部特征,提取到的局部特征包含以下信息:描述子,方位(x,y),尺度信息,主方向信息等。
在对描述子量化时,需要对描述子进行分组量化。在我们的方法中使用的描述子是32维,在这里将其划分为4组。这里将每组描述子先行量化,然后通过乘积量化的方法再组合起来。对于每组的量化如下所示:
在分组量化时,对于每组的描述子分别与视觉词典中对应组的词根使用如下公式分别计算。选取计算结果最小的词根的下标来表示该描述子。(下方有代码,参考代码有助于理解公式)
其中i表示该组描述子的第i维,j表示第j组。Vj是视觉词典中对应组词根的下标,用于表示第j组的量化结果。如上图中,第i组的量化结果为1。
通过上述公式对所有组的描述子进行量化,对于各组的量化结果采用下面公式进行乘积组合。最后得到的结果作为视觉词汇用于表示该局部特征。
这里给了一份我们使用的视觉词汇词典的一组的词根,一共64个词根,每个词根8维,如图所示:
这是我们通过聚类学习得到第2组的视觉词典的词根。
量化需要的乘积量化的关键代码如下所示:
public virtualUInt32 Quanting(double[] feat)
{
UInt32 result = 0;
for (int i = 0; i < means.GetLength(0);i++)//对第i组量化
{
double minDis = double.MaxValue;
int idx = -1;
for (int j = 0; j < means.GetLength(1);j++)//第i组的第j个词根,如上图所示,我们的词典的词根为64个
{
double dis =0;
for (int k = 0; k < means.GetLength(2);k++)//每个词根的维度,我们的方法是每个词根8维
{
dis += (means[i, j, k]- feat[8 * i + k]) * (means[i, j, k] - feat[8 * i + k]);
}
if (dis < minDis)
{
minDis = dis;
idx = j;
}
}
//将第一组的量化结果放在高位,最后一组放在最低的一些位上
result *= (UInt32)stepNum;//这里采用上文所述的乘积量化
result += (UInt32)idx;
}
return result;
}
最后result就是所要得到的视觉词汇visual word了。
以上就是该算法的量化所有内容,有兴趣的同学可以交流一下。