CBIR:BoW概念和使用

本文深入探讨了基于视觉单词的BoW(Bag of Words)概念及其在图像检索领域的应用。通过构建词典和计算图像特征在词典中的分布,BoW 提供了一种高效的方法来匹配和查找相似图片,显著提高了匹配速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。


本demo实现的是基于bow原理对图片进行分类,并实现对选取得测试集进行查找 BoW(Bag of Words)词袋模型最初被用在文本分类中,将文档表示成特征矢量。它的基本思想是假定对于一个文本,忽略其词序语法、句法,仅仅将其看做是一些词汇的集合,而文本中的每个词汇都是独立的。简单说就是讲每篇文档都看成一个袋子(因为里面装的都是词汇,所以称为词袋,Bag of words即因此而来),然后看这个袋子里装的都是些什么词汇,将其分类。如果文档中猪、马、牛、羊、山谷、土地、拖拉机这样的词汇多些,而银行、大厦、汽车、公园这样的词汇少些,我们就倾向于判断它是一篇描绘乡村的文档,而不是描述城镇的。 serachFeatures.py中,前面主要是一些通过parse使得可以在敲命令行的时候可以向里面传递参数,后面就是提取SIFT特征,然后聚类,计算TFIDF,得到单词直方图后再做一下L2归一化。一般在一幅图像中提取的到SIFT特征点是非常多的,而如果图像库很大的话,SIFT特征点会非常非常的多,直接聚类是非常困难的(内存不够,计算速度非常慢),所以,为了解决这个问题,可以以牺牲检索精度为代价,在聚类的时候先对SIFT做降采样处理。最后对一些在在线查询时会用到的变量保存下来。对于某个图像库,我们可以在命令行里通过下面命令生成BoF。 query.py只能每次查找一张图片,并返回与之匹配度(递减)最接近的6张图片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值