BoVW (Bag of Visual Word) 是在传统图像检索领域里比较常用的一种方法。大体可以分为三个步骤:特征提取,聚类 (类似于寻找一组基), 计算图片在基上的坐标。算法的创新点是对图片的特征寻找基。这样,在基固定的情况下,所有的图片都可以使用这组基来唯一的表示。而且,由于基的维数是固定的,也为相似度计算提供了极大的方便。根据检索图片的不同,可以选用不同的特征提取方法。
特征提取
根据检索图片的特点,可以选用不同的特征提取方法,最终,图像中的特征要映射到一组基上面。
聚类
聚类的目的是为了给图片的特征寻找一组合适的基 (大部分时候论文中叫做簇,为了方便理解,这里仍然使用基这个名词). 聚类的中心点的个数需要自定义。一般情况,聚类中心的数量要大于一张图片中的特征的数量。假设一张图片中特征的数量是 \(n\), 我比较喜欢选择的聚类中心的数量是 \(kn^2\). 这样做的目的是为了图片特征表达的稀疏性。为了理解这一点,假设选择的聚类中心个数为\(2\), 那么,每张图片中提取的特征的数量是\(100\), 那么,这种情况下,所有不同的坐标个数是 \(101\), 也就是说,最理想的情况下,这种方法能够检索的图像的数量是\(101\) 张。如果聚类中心数量为\(1000\), 好吧,我暂时没有计算出来具体数字.o(╯□╰)o 反正是一个好大好大的数字。
由于从 train set 中提取的特征的数量特别多 (比如,每张图片 1000 个特征,10000 张图片的话就是 1kw 的特征), 如果直接聚类的话 (聚类中心为 \(10^3\) 量级), 由于 sample 的数量特别多,聚类时长无法接受,常用的做法是先进行抽样,然后用抽样得到的样本进行聚类。抽样又有两种方法,一种是对原始图片进行抽样,然后对样本图片提取特征,聚类。另外一种做法是对全部图片的特征进行抽样,然后对抽样特征进行聚类。
计算坐标
通过聚类,我们得到了一个模型,假设该,模型的聚类中心的数量是 \(\cal N\), 并且赋予聚类中心顺序,那么,使用该聚类模型对 train set 中的每一张图片的特征进行预测,得到这张图片每一个特征所在的聚类中心\(P\), 计算\(P\) 的 histogram, 就的到了相应的 \(\cal N\) 维的特征。如果每一张图片提取的特征的数量不同 (例如 SIFT 特征)(即使相同,也推荐做一下归一化), 那么,还需要对 histogram 做一个归一化操作。这样,就可以得到每一张图片一个 \(\cal N\) 维的 code.
检索
对一张图片,计算其 code, 然后和 train set 中的图片的 code 比较距离。距离越近越相似,说明图片越相似。
训练代码
1 | import cv2 |
思考
由于对特征进行聚类之后计算 histogram, 把 histogram 的结果用来计算相似度,所以,这就损失了原始特征在图片中的位置信息。一种比较直观的方法是对图片先进行分块,对每一块计算其 code, 然后把所有快的 code 组合到一起进行比较相似度,但是,这种方法又损失和旋转不变性和平移不变性。