CBIR:BoW概念和使用

CBIR:BoW概念和使用




以前自己看过关于CBIR的一些知识,也就是相似图片的检索。比如我的图片库有N张图片,现在我拿出一张图片到N张图片中去检索,目标是找到和当前图片最相似的(具备很多相同的特征)。最近随着几个月每天加班的Web项目完成后,又有时间回过头来思考了一下这个问题。

在图片库比较小的情况下,可以采取循环遍历所有特征,每一个都和目标图片进行匹配,找出几个匹配最好的。之前某个项目就采取了这样的办法。当时为了增大匹配速度,对于特征点的特征向量,建立了较为有效的索引机制,通过索引大约可以规避掉95%以上无效匹配。对于小的图片库(小于几百)这样也就足够了。

当图片库进一步增大,就必须考虑更加具有效率的方式了。首先从OpenCV的标准函数入手,也就是BOWKMeansTrainer。


首先学习一下BoW的概念。对于任意图像来说。都是由多个特征组成的。我们可以把组成它的这些特征放到一个Bag里面去。如上图。也就是把一幅图类比为多个它所具备的特征的集合。

现在假设我们有N张图片,我们从N张图片中提取所有的特征出来,由于N张图的特征非常多,如果把N张图的特征都装入一个袋子里面去。这个袋子就太大了,实际上它是一个词典。也就是说这个词典包含了所有N张图的特征。

基于以上知识,然后再考虑一下如何查找相似匹配的问题。如果每张图都可以用一个装满特征的Bag来表示,那么比较两幅图的相似程度,可以直接比较这两个Bag的相似程度。

如上图对于每一个Bag,我们根据它装的是词典里面的哪些特征词,可以计算出它所包含的特征分布图。对于不同的Bag,显然特征分布图越接近,就代表两个Bag之间的相似程度越大。

在没有使用BoW之前,我们假设每张图片有300个特征,比较两幅图的相似程度,实际上是用A图的300特征和B图的300特征比较。这么大的数量造成了匹配的复杂程度非常高。如果基于BoW,考虑一下只比较两个Bag的相似程度。每一个Bag用特征分布的直方图表示,在OpenCV中表示为一个Matrix,比较两个Matrix的相似度,只要一句话就解决了。这样可以大大提高查找的效率。

实际上基于这个Bag,可以继续使用SVM等等进行训练归类等等。由于我的目标和这个稍微差距,所以就不讨论这些问题了。

对于该系统的实现,第一个部分是计算词典。也就是全部图的特征集合。

dictionary=bowTrainer.cluster(featuresUnclustered);

第二部分是计算每幅图的特征词在词典中的分布

cv::BOWImgDescriptorExtractor bowDE(matcher);
bowDE.compute(descriptors,bowDescriptor);

第三部分是比较两幅图的相似程度时,直接匹配:

for(int i = 0; i < m_samples.size(); i++){
    float score = cv::norm(m_samples[i], bowDescriptor,
           cv::NORM_L2SQR);
    allScores.push_back(std::pair<float,int>(score,i));
}

最后匹配的score排序一下,选几个最好的出来。

代码部分参考:Bag-of-Features Descriptor on SIFT Features with OpenCV (BoF-SIFT)


后记:

BoW的速度比起循环遍历特征还是强很多很多的。毕竟对于N张图片,只需要N次匹配再排序。不过我在实验中发现对于实际中摄像头拍到的有些图存在错误率太高的问题(一定是打开的方式不对)。对于如何提高成功率,如果有过这方面经验的前辈们请多多指教。

另外,当N过大时,N次匹配也是不能接受的(假设N=100000)。下一篇打算谈一谈Vocabulary Tree。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值